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

Side by Side Diff: Source/modules/accessibility/AXLayoutObject.cpp

Issue 1076453004: Show reasons why nodes are ignored in accessibility sidebar (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Removing IgnoredReasons from protocol Created 5 years, 8 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
« no previous file with comments | « Source/devtools/protocol.json ('k') | Source/modules/accessibility/AXNodeObject.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 } 461 }
462 462
463 // 463 //
464 // Whether objects are ignored, i.e. not included in the tree. 464 // Whether objects are ignored, i.e. not included in the tree.
465 // 465 //
466 466
467 AXObjectInclusion AXLayoutObject::defaultObjectInclusion(IgnoredReasons* ignored Reasons) const 467 AXObjectInclusion AXLayoutObject::defaultObjectInclusion(IgnoredReasons* ignored Reasons) const
468 { 468 {
469 // The following cases can apply to any element that's a subclass of AXLayou tObject. 469 // The following cases can apply to any element that's a subclass of AXLayou tObject.
470 470
471 if (!m_layoutObject) 471 if (!m_layoutObject) {
472 if (ignoredReasons)
473 ignoredReasons->append(IgnoredReason(AXNotRendered));
472 return IgnoreObject; 474 return IgnoreObject;
475 }
473 476
474 if (m_layoutObject->style()->visibility() != VISIBLE) { 477 if (m_layoutObject->style()->visibility() != VISIBLE) {
475 // aria-hidden is meant to override visibility as the determinant in AX hierarchy inclusion. 478 // aria-hidden is meant to override visibility as the determinant in AX hierarchy inclusion.
476 if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "false")) 479 if (equalIgnoringCase(getAttribute(aria_hiddenAttr), "false"))
477 return DefaultBehavior; 480 return DefaultBehavior;
478 481
482 if (ignoredReasons)
483 ignoredReasons->append(IgnoredReason(AXNotVisible));
479 return IgnoreObject; 484 return IgnoreObject;
480 } 485 }
481 486
482 return AXObject::defaultObjectInclusion(ignoredReasons); 487 return AXObject::defaultObjectInclusion(ignoredReasons);
483 } 488 }
484 489
485 bool AXLayoutObject::computeAccessibilityIsIgnored(IgnoredReasons* ignoredReason s) const 490 bool AXLayoutObject::computeAccessibilityIsIgnored(IgnoredReasons* ignoredReason s) const
486 { 491 {
487 #if ENABLE(ASSERT) 492 #if ENABLE(ASSERT)
488 ASSERT(m_initialized); 493 ASSERT(m_initialized);
489 #endif 494 #endif
490 495
491 // Check first if any of the common reasons cause this element to be ignored . 496 // Check first if any of the common reasons cause this element to be ignored .
492 // Then process other use cases that need to be applied to all the various r oles 497 // Then process other use cases that need to be applied to all the various r oles
493 // that AXLayoutObjects take on. 498 // that AXLayoutObjects take on.
494 AXObjectInclusion decision = defaultObjectInclusion(ignoredReasons); 499 AXObjectInclusion decision = defaultObjectInclusion(ignoredReasons);
495 if (decision == IncludeObject) 500 if (decision == IncludeObject)
496 return false; 501 return false;
497 if (decision == IgnoreObject) 502 if (decision == IgnoreObject)
498 return true; 503 return true;
499 504
500 // If this element is within a parent that cannot have children, it should n ot be exposed. 505 // If this element is within a parent that cannot have children, it should n ot be exposed
501 if (isDescendantOfLeafNode()) 506 if (isDescendantOfLeafNode()) {
507 if (ignoredReasons)
508 ignoredReasons->append(IgnoredReason(AXAncestorIsLeafNode, leafNodeA ncestor()));
502 return true; 509 return true;
510 }
503 511
504 if (roleValue() == IgnoredRole) 512 if (roleValue() == IgnoredRole) {
dmazzoni 2015/04/23 05:28:38 Worth cleaning this up maybe. The only two places
aboxhall 2015/04/28 02:36:11 I'd prefer to try not to make any functional chang
513 if (ignoredReasons) {
514 ignoredReasons->append(IgnoredReason(AXUninteresting));
515 }
505 return true; 516 return true;
517 }
506 518
507 if (hasInheritedPresentationalRole()) 519 if (hasInheritedPresentationalRole()) {
520 if (ignoredReasons)
521 ignoredReasons->append(IgnoredReason(AXInheritsPresentation, inherit sPresentationalRoleFrom()));
508 return true; 522 return true;
523 }
509 524
510 // An ARIA tree can only have tree items and static text as children. 525 // An ARIA tree can only have tree items and static text as children.
511 if (treeAncestorDisallowingChild()) 526 if (AXObject* treeAncestor = treeAncestorDisallowingChild()) {
527 if (ignoredReasons)
528 ignoredReasons->append(IgnoredReason(AXAncestorDisallowsChild, treeA ncestor));
512 return true; 529 return true;
530 }
513 531
514 // TODO: we should refactor this - but right now this is necessary to make 532 // TODO: we should refactor this - but right now this is necessary to make
515 // sure scroll areas stay in the tree. 533 // sure scroll areas stay in the tree.
516 if (isAttachment()) 534 if (isAttachment())
517 return false; 535 return false;
518 536
519 // ignore popup menu items because AppKit does 537 // ignore popup menu items because AppKit does
dmazzoni 2015/04/23 05:28:38 ooh, I think my recent change made this block unne
aboxhall 2015/04/28 02:36:11 Done.
520 for (LayoutObject* parent = m_layoutObject->parent(); parent; parent = paren t->parent()) { 538 for (LayoutObject* parent = m_layoutObject->parent(); parent; parent = paren t->parent()) {
521 if (parent->isBoxModelObject() && toLayoutBoxModelObject(parent)->isMenu List()) 539 if (parent->isBoxModelObject() && toLayoutBoxModelObject(parent)->isMenu List()) {
540 if (ignoredReasons) {
541 AXObject* parentObject = axObjectCache()->getOrCreate(parent);
542 if (parentObject)
543 ignoredReasons->append(IgnoredReason(AXAncestorDisallowsChil d, parentObject));
544 }
522 return true; 545 return true;
546 }
523 } 547 }
524 548
525 // find out if this element is inside of a label element. 549 // find out if this element is inside of a label element.
526 // if so, it may be ignored because it's the label for a checkbox or radio b utton 550 // if so, it may be ignored because it's the label for a checkbox or radio b utton
527 AXObject* controlObject = correspondingControlForLabelElement(); 551 AXObject* controlObject = correspondingControlForLabelElement();
528 if (controlObject && !controlObject->deprecatedExposesTitleUIElement() && co ntrolObject->isCheckboxOrRadio()) 552 if (controlObject && !controlObject->deprecatedExposesTitleUIElement() && co ntrolObject->isCheckboxOrRadio()) {
553 if (ignoredReasons) {
554 HTMLLabelElement* label = labelElementContainer();
555 if (label && !label->isSameNode(node())) {
556 AXObject* labelAXObject = axObjectCache()->getOrCreate(label);
557 ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXOb ject));
dmazzoni 2015/04/23 05:28:38 Null-check labelAXObject, even if there isn't any
aboxhall 2015/04/28 02:36:11 There's nothing I can really do about it if it's n
558 }
559
560 ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject));
561 }
529 return true; 562 return true;
563 }
530 564
531 if (m_layoutObject->isBR()) 565 if (m_layoutObject->isBR())
532 return false; 566 return false;
533 567
534 // NOTE: BRs always have text boxes now, so the text box check here can be r emoved
535 if (m_layoutObject->isText()) { 568 if (m_layoutObject->isText()) {
536 // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level 569 // static text beneath MenuItems and MenuButtons are just reported along with the menu item, so it's ignored on an individual level
537 AXObject* parent = parentObjectUnignored(); 570 AXObject* parent = parentObjectUnignored();
538 if (parent && (parent->ariaRoleAttribute() == MenuItemRole || parent->ar iaRoleAttribute() == MenuButtonRole)) 571 if (parent && (parent->ariaRoleAttribute() == MenuItemRole || parent->ar iaRoleAttribute() == MenuButtonRole)) {
572 if (ignoredReasons)
573 ignoredReasons->append(IgnoredReason(AXStaticTextUsedAsNameFor, parent));
539 return true; 574 return true;
575 }
540 LayoutText* layoutText = toLayoutText(m_layoutObject); 576 LayoutText* layoutText = toLayoutText(m_layoutObject);
541 if (m_layoutObject->isBR() || !layoutText->firstTextBox()) 577 if (!layoutText->firstTextBox()) {
578 if (ignoredReasons)
579 ignoredReasons->append(IgnoredReason(AXEmptyText));
542 return true; 580 return true;
581 }
543 582
544 // Don't ignore static text in editable text controls. 583 // Don't ignore static text in editable text controls.
545 for (AXObject* parent = parentObject(); parent; parent = parent->parentO bject()) { 584 for (AXObject* parent = parentObject(); parent; parent = parent->parentO bject()) {
546 if (parent->roleValue() == TextFieldRole) 585 if (parent->roleValue() == TextFieldRole)
547 return false; 586 return false;
548 } 587 }
549 588
550 // text elements that are just empty whitespace should not be returned 589 // text elements that are just empty whitespace should not be returned
551 // FIXME(dmazzoni): we probably shouldn't ignore this if the style is 'p re', or similar... 590 // FIXME(dmazzoni): we probably shouldn't ignore this if the style is 'p re', or similar...
552 return layoutText->text().impl()->containsOnlyWhitespace(); 591 if (layoutText->text().impl()->containsOnlyWhitespace()) {
592 if (ignoredReasons)
593 ignoredReasons->append(IgnoredReason(AXEmptyText));
594 return true;
595 }
596 return false;
553 } 597 }
554 598
555 if (isHeading()) 599 if (isHeading())
556 return false; 600 return false;
557 601
558 if (isLandmarkRelated()) 602 if (isLandmarkRelated())
559 return false; 603 return false;
560 604
561 if (isLink()) 605 if (isLink())
562 return false; 606 return false;
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 // if this element has aria attributes on it, it should not be ignored. 654 // if this element has aria attributes on it, it should not be ignored.
611 if (supportsARIAAttributes()) 655 if (supportsARIAAttributes())
612 return false; 656 return false;
613 657
614 // <span> tags are inline tags and not meant to convey information if they h ave no other aria 658 // <span> tags are inline tags and not meant to convey information if they h ave no other aria
615 // information on them. If we don't ignore them, they may emit signals expec ted to come from 659 // information on them. If we don't ignore them, they may emit signals expec ted to come from
616 // their parent. In addition, because included spans are GroupRole objects, and GroupRole 660 // their parent. In addition, because included spans are GroupRole objects, and GroupRole
617 // objects are often containers with meaningful information, the inclusion o f a span can have 661 // objects are often containers with meaningful information, the inclusion o f a span can have
618 // the side effect of causing the immediate parent accessible to be ignored. This is especially 662 // the side effect of causing the immediate parent accessible to be ignored. This is especially
619 // problematic for platforms which have distinct roles for textual block ele ments. 663 // problematic for platforms which have distinct roles for textual block ele ments.
620 if (isHTMLSpanElement(node)) 664 if (isHTMLSpanElement(node)) {
dmazzoni 2015/04/23 05:28:38 fwiw, i'd like to get rid of this rule. there's no
aboxhall 2015/04/28 02:36:11 Agreed. Let's chat about this for the follow up re
665 if (ignoredReasons)
666 ignoredReasons->append(IgnoredReason(AXUninteresting));
621 return true; 667 return true;
668 }
622 669
623 if (m_layoutObject->isLayoutBlockFlow() && m_layoutObject->childrenInline() && !canSetFocusAttribute()) 670 if (m_layoutObject->isLayoutBlockFlow() && m_layoutObject->childrenInline() && !canSetFocusAttribute()) {
624 return !toLayoutBlockFlow(m_layoutObject)->firstLineBox() && !mouseButto nListener(); 671 if (toLayoutBlockFlow(m_layoutObject)->firstLineBox() || mouseButtonList ener())
672 return false;
673
674 if (ignoredReasons)
675 ignoredReasons->append(IgnoredReason(AXUninteresting));
676 return true;
677 }
625 678
626 // ignore images seemingly used as spacers 679 // ignore images seemingly used as spacers
627 if (isImage()) { 680 if (isImage()) {
628 681
629 // If the image can take focus, it should not be ignored, lest the user not be able to interact with something important. 682 // If the image can take focus, it should not be ignored, lest the user not be able to interact with something important.
630 if (canSetFocusAttribute()) 683 if (canSetFocusAttribute())
631 return false; 684 return false;
632 685
633 if (node && node->isElementNode()) { 686 if (node && node->isElementNode()) {
634 Element* elt = toElement(node); 687 Element* elt = toElement(node);
635 const AtomicString& alt = elt->getAttribute(altAttr); 688 const AtomicString& alt = elt->getAttribute(altAttr);
636 // don't ignore an image that has an alt tag 689 // don't ignore an image that has an alt tag
637 if (!alt.string().containsOnlyWhitespace()) 690 if (!alt.string().containsOnlyWhitespace())
638 return false; 691 return false;
639 // informal standard is to ignore images with zero-length alt string s 692 // informal standard is to ignore images with zero-length alt string s
640 if (!alt.isNull()) 693 if (!alt.isNull()) {
694 if (ignoredReasons)
695 ignoredReasons->append(IgnoredReason(AXEmptyAlt));
641 return true; 696 return true;
697 }
642 } 698 }
643 699
644 if (isNativeImage() && m_layoutObject->isImage()) { 700 if (isNativeImage() && m_layoutObject->isImage()) {
645 // check for one-dimensional image 701 // check for one-dimensional image
646 LayoutImage* image = toLayoutImage(m_layoutObject); 702 LayoutImage* image = toLayoutImage(m_layoutObject);
647 if (image->size().height() <= 1 || image->size().width() <= 1) 703 if (image->size().height() <= 1 || image->size().width() <= 1) {
704 if (ignoredReasons)
705 ignoredReasons->append(IgnoredReason(AXProbablyPresentationa l));
dmazzoni 2015/04/23 05:28:38 How about an explicit reason for this one, like AX
aboxhall 2015/04/28 02:36:11 I figured this was more on the heuristic side.
648 return true; 706 return true;
707 }
649 708
650 // check whether laid out image was stretched from one-dimensional f ile image 709 // check whether laid out image was stretched from one-dimensional f ile image
651 if (image->cachedImage()) { 710 if (image->cachedImage()) {
652 LayoutSize imageSize = image->cachedImage()->imageSizeForLayoutO bject(m_layoutObject, image->view()->zoomFactor()); 711 LayoutSize imageSize = image->cachedImage()->imageSizeForLayoutO bject(m_layoutObject, image->view()->zoomFactor());
653 return imageSize.height() <= 1 || imageSize.width() <= 1; 712 if (imageSize.height() <= 1 || imageSize.width() <= 1) {
713 if (ignoredReasons)
714 ignoredReasons->append(IgnoredReason(AXProbablyPresentat ional));
dmazzoni 2015/04/23 05:28:38 Same
aboxhall 2015/04/28 02:36:11 As above.
715 return true;
716 }
717 return false;
654 } 718 }
655 } 719 }
656 return false; 720 return false;
657 } 721 }
658 722
659 if (isCanvas()) { 723 if (isCanvas()) {
660 if (canvasHasFallbackContent()) 724 if (canvasHasFallbackContent())
661 return false; 725 return false;
662 LayoutHTMLCanvas* canvas = toLayoutHTMLCanvas(m_layoutObject); 726 LayoutHTMLCanvas* canvas = toLayoutHTMLCanvas(m_layoutObject);
663 if (canvas->size().height() <= 1 || canvas->size().width() <= 1) 727 if (canvas->size().height() <= 1 || canvas->size().width() <= 1) {
728 if (ignoredReasons)
729 ignoredReasons->append(IgnoredReason(AXProbablyPresentational));
dmazzoni 2015/04/23 05:28:38 Same
aboxhall 2015/04/28 02:36:11 As above.
664 return true; 730 return true;
731 }
665 // Otherwise fall through; use presence of help text, title, or descript ion to decide. 732 // Otherwise fall through; use presence of help text, title, or descript ion to decide.
666 } 733 }
667 734
668 if (isWebArea() || m_layoutObject->isListMarker()) 735 if (isWebArea() || m_layoutObject->isListMarker())
669 return false; 736 return false;
670 737
671 // Using the help text, title or accessibility description (so we 738 // Using the help text, title or accessibility description (so we
672 // check if there's some kind of accessible name for the element) 739 // check if there's some kind of accessible name for the element)
673 // to decide an element's visibility is not as definitive as 740 // to decide an element's visibility is not as definitive as
674 // previous checks, so this should remain as one of the last. 741 // previous checks, so this should remain as one of the last.
675 // 742 //
676 // These checks are simplified in the interest of execution speed; 743 // These checks are simplified in the interest of execution speed;
677 // for example, any element having an alt attribute will make it 744 // for example, any element having an alt attribute will make it
678 // not ignored, rather than just images. 745 // not ignored, rather than just images.
679 if (!getAttribute(aria_helpAttr).isEmpty() || !getAttribute(aria_describedby Attr).isEmpty() || !getAttribute(altAttr).isEmpty() || !getAttribute(titleAttr). isEmpty()) 746 if (!getAttribute(aria_helpAttr).isEmpty() || !getAttribute(aria_describedby Attr).isEmpty() || !getAttribute(altAttr).isEmpty() || !getAttribute(titleAttr). isEmpty())
680 return false; 747 return false;
681 748
682 // Don't ignore generic focusable elements like <div tabindex=0> 749 // Don't ignore generic focusable elements like <div tabindex=0>
683 // unless they're completely empty, with no children. 750 // unless they're completely empty, with no children.
684 if (isGenericFocusableElement() && node->hasChildren()) 751 if (isGenericFocusableElement() && node->hasChildren())
685 return false; 752 return false;
686 753
687 if (!ariaAccessibilityDescription().isEmpty()) 754 if (!ariaAccessibilityDescription().isEmpty())
688 return false; 755 return false;
689 756
690 // By default, objects should be ignored so that the AX hierarchy is not 757 // By default, objects should be ignored so that the AX hierarchy is not
691 // filled with unnecessary items. 758 // filled with unnecessary items.
759 if (ignoredReasons)
760 ignoredReasons->append(IgnoredReason(AXUninteresting));
dmazzoni 2015/04/23 05:28:38 If we skip <span>, it should be handled here. To
aboxhall 2015/04/28 02:36:11 Acknowledged.
692 return true; 761 return true;
693 } 762 }
694 763
695 // 764 //
696 // Properties of static elements. 765 // Properties of static elements.
697 // 766 //
698 767
699 const AtomicString& AXLayoutObject::accessKey() const 768 const AtomicString& AXLayoutObject::accessKey() const
700 { 769 {
701 Node* node = m_layoutObject->node(); 770 Node* node = m_layoutObject->node();
(...skipping 1574 matching lines...) Expand 10 before | Expand all | Expand 10 after
2276 if (label && label->layoutObject()) { 2345 if (label && label->layoutObject()) {
2277 LayoutRect labelRect = axObjectCache()->getOrCreate(label)->elementR ect(); 2346 LayoutRect labelRect = axObjectCache()->getOrCreate(label)->elementR ect();
2278 result.unite(labelRect); 2347 result.unite(labelRect);
2279 } 2348 }
2280 } 2349 }
2281 2350
2282 return result; 2351 return result;
2283 } 2352 }
2284 2353
2285 } // namespace blink 2354 } // namespace blink
OLDNEW
« no previous file with comments | « Source/devtools/protocol.json ('k') | Source/modules/accessibility/AXNodeObject.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698