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

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: Add a catch-all return to ignoredReasonName Created 5 years, 7 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) {
513 if (ignoredReasons)
514 ignoredReasons->append(IgnoredReason(AXUninteresting));
505 return true; 515 return true;
516 }
506 517
507 if (hasInheritedPresentationalRole()) 518 if (hasInheritedPresentationalRole()) {
519 if (ignoredReasons) {
520 const AXObject* inheritsFrom = inheritsPresentationalRoleFrom();
521 if (inheritsFrom == this)
522 ignoredReasons->append(IgnoredReason(AXPresentationalRole));
523 else
524 ignoredReasons->append(IgnoredReason(AXInheritsPresentation, inh eritsFrom));
525 }
508 return true; 526 return true;
527 }
509 528
510 // An ARIA tree can only have tree items and static text as children. 529 // An ARIA tree can only have tree items and static text as children.
511 if (treeAncestorDisallowingChild()) 530 if (AXObject* treeAncestor = treeAncestorDisallowingChild()) {
531 if (ignoredReasons)
532 ignoredReasons->append(IgnoredReason(AXAncestorDisallowsChild, treeA ncestor));
512 return true; 533 return true;
534 }
513 535
514 // TODO: we should refactor this - but right now this is necessary to make 536 // TODO: we should refactor this - but right now this is necessary to make
515 // sure scroll areas stay in the tree. 537 // sure scroll areas stay in the tree.
516 if (isAttachment()) 538 if (isAttachment())
517 return false; 539 return false;
518 540
519 // ignore popup menu items because AppKit does
520 for (LayoutObject* parent = m_layoutObject->parent(); parent; parent = paren t->parent()) {
521 if (parent->isBoxModelObject() && toLayoutBoxModelObject(parent)->isMenu List())
522 return true;
523 }
524
525 // find out if this element is inside of a label element. 541 // 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 542 // if so, it may be ignored because it's the label for a checkbox or radio b utton
527 AXObject* controlObject = correspondingControlForLabelElement(); 543 AXObject* controlObject = correspondingControlForLabelElement();
528 if (controlObject && !controlObject->deprecatedExposesTitleUIElement() && co ntrolObject->isCheckboxOrRadio()) 544 if (controlObject && !controlObject->deprecatedExposesTitleUIElement() && co ntrolObject->isCheckboxOrRadio()) {
545 if (ignoredReasons) {
546 HTMLLabelElement* label = labelElementContainer();
547 if (label && !label->isSameNode(node())) {
548 AXObject* labelAXObject = axObjectCache()->getOrCreate(label);
549 ignoredReasons->append(IgnoredReason(AXLabelContainer, labelAXOb ject));
550 }
551
552 ignoredReasons->append(IgnoredReason(AXLabelFor, controlObject));
553 }
529 return true; 554 return true;
555 }
530 556
531 if (m_layoutObject->isBR()) 557 if (m_layoutObject->isBR())
532 return false; 558 return false;
533 559
534 // NOTE: BRs always have text boxes now, so the text box check here can be r emoved
535 if (m_layoutObject->isText()) { 560 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 561 // 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(); 562 AXObject* parent = parentObjectUnignored();
538 if (parent && (parent->ariaRoleAttribute() == MenuItemRole || parent->ar iaRoleAttribute() == MenuButtonRole)) 563 if (parent && (parent->ariaRoleAttribute() == MenuItemRole || parent->ar iaRoleAttribute() == MenuButtonRole)) {
564 if (ignoredReasons)
565 ignoredReasons->append(IgnoredReason(AXStaticTextUsedAsNameFor, parent));
539 return true; 566 return true;
567 }
540 LayoutText* layoutText = toLayoutText(m_layoutObject); 568 LayoutText* layoutText = toLayoutText(m_layoutObject);
541 if (m_layoutObject->isBR() || !layoutText->firstTextBox()) 569 if (!layoutText->firstTextBox()) {
570 if (ignoredReasons)
571 ignoredReasons->append(IgnoredReason(AXEmptyText));
542 return true; 572 return true;
573 }
543 574
544 // Don't ignore static text in editable text controls. 575 // Don't ignore static text in editable text controls.
545 for (AXObject* parent = parentObject(); parent; parent = parent->parentO bject()) { 576 for (AXObject* parent = parentObject(); parent; parent = parent->parentO bject()) {
546 if (parent->roleValue() == TextFieldRole) 577 if (parent->roleValue() == TextFieldRole)
547 return false; 578 return false;
548 } 579 }
549 580
550 // text elements that are just empty whitespace should not be returned 581 // 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... 582 // FIXME(dmazzoni): we probably shouldn't ignore this if the style is 'p re', or similar...
552 return layoutText->text().impl()->containsOnlyWhitespace(); 583 if (layoutText->text().impl()->containsOnlyWhitespace()) {
584 if (ignoredReasons)
585 ignoredReasons->append(IgnoredReason(AXEmptyText));
586 return true;
587 }
588 return false;
553 } 589 }
554
555 if (isHeading()) 590 if (isHeading())
556 return false; 591 return false;
557 592
558 if (isLandmarkRelated()) 593 if (isLandmarkRelated())
559 return false; 594 return false;
560 595
561 if (isLink()) 596 if (isLink())
562 return false; 597 return false;
563 598
564 // all controls are accessible 599 // all controls are accessible
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 // if this element has aria attributes on it, it should not be ignored. 645 // if this element has aria attributes on it, it should not be ignored.
611 if (supportsARIAAttributes()) 646 if (supportsARIAAttributes())
612 return false; 647 return false;
613 648
614 // <span> tags are inline tags and not meant to convey information if they h ave no other aria 649 // <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 650 // 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 651 // 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 652 // 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 653 // 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. 654 // problematic for platforms which have distinct roles for textual block ele ments.
620 if (isHTMLSpanElement(node)) 655 if (isHTMLSpanElement(node)) {
656 if (ignoredReasons)
657 ignoredReasons->append(IgnoredReason(AXUninteresting));
621 return true; 658 return true;
659 }
622 660
623 if (m_layoutObject->isLayoutBlockFlow() && m_layoutObject->childrenInline() && !canSetFocusAttribute()) 661 if (m_layoutObject->isLayoutBlockFlow() && m_layoutObject->childrenInline() && !canSetFocusAttribute()) {
624 return !toLayoutBlockFlow(m_layoutObject)->firstLineBox() && !mouseButto nListener(); 662 if (toLayoutBlockFlow(m_layoutObject)->firstLineBox() || mouseButtonList ener())
663 return false;
664
665 if (ignoredReasons)
666 ignoredReasons->append(IgnoredReason(AXUninteresting));
667 return true;
668 }
625 669
626 // ignore images seemingly used as spacers 670 // ignore images seemingly used as spacers
627 if (isImage()) { 671 if (isImage()) {
628
629 // If the image can take focus, it should not be ignored, lest the user not be able to interact with something important. 672 // 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()) 673 if (canSetFocusAttribute())
631 return false; 674 return false;
632 675
633 if (node && node->isElementNode()) { 676 if (node && node->isElementNode()) {
634 Element* elt = toElement(node); 677 Element* elt = toElement(node);
635 const AtomicString& alt = elt->getAttribute(altAttr); 678 const AtomicString& alt = elt->getAttribute(altAttr);
636 // don't ignore an image that has an alt tag 679 // don't ignore an image that has an alt tag
637 if (!alt.string().containsOnlyWhitespace()) 680 if (!alt.string().containsOnlyWhitespace())
638 return false; 681 return false;
639 // informal standard is to ignore images with zero-length alt string s 682 // informal standard is to ignore images with zero-length alt string s
640 if (!alt.isNull()) 683 if (!alt.isNull()) {
684 if (ignoredReasons)
685 ignoredReasons->append(IgnoredReason(AXEmptyAlt));
641 return true; 686 return true;
687 }
642 } 688 }
643 689
644 if (isNativeImage() && m_layoutObject->isImage()) { 690 if (isNativeImage() && m_layoutObject->isImage()) {
645 // check for one-dimensional image 691 // check for one-dimensional image
646 LayoutImage* image = toLayoutImage(m_layoutObject); 692 LayoutImage* image = toLayoutImage(m_layoutObject);
647 if (image->size().height() <= 1 || image->size().width() <= 1) 693 if (image->size().height() <= 1 || image->size().width() <= 1) {
694 if (ignoredReasons)
695 ignoredReasons->append(IgnoredReason(AXProbablyPresentationa l));
648 return true; 696 return true;
697 }
649 698
650 // check whether laid out image was stretched from one-dimensional f ile image 699 // check whether laid out image was stretched from one-dimensional f ile image
651 if (image->cachedImage()) { 700 if (image->cachedImage()) {
652 LayoutSize imageSize = image->cachedImage()->imageSizeForLayoutO bject(m_layoutObject, image->view()->zoomFactor()); 701 LayoutSize imageSize = image->cachedImage()->imageSizeForLayoutO bject(m_layoutObject, image->view()->zoomFactor());
653 return imageSize.height() <= 1 || imageSize.width() <= 1; 702 if (imageSize.height() <= 1 || imageSize.width() <= 1) {
703 if (ignoredReasons)
704 ignoredReasons->append(IgnoredReason(AXProbablyPresentat ional));
705 return true;
706 }
707 return false;
654 } 708 }
655 } 709 }
656 return false; 710 return false;
657 } 711 }
658 712
659 if (isCanvas()) { 713 if (isCanvas()) {
660 if (canvasHasFallbackContent()) 714 if (canvasHasFallbackContent())
661 return false; 715 return false;
662 LayoutHTMLCanvas* canvas = toLayoutHTMLCanvas(m_layoutObject); 716 LayoutHTMLCanvas* canvas = toLayoutHTMLCanvas(m_layoutObject);
663 if (canvas->size().height() <= 1 || canvas->size().width() <= 1) 717 if (canvas->size().height() <= 1 || canvas->size().width() <= 1) {
718 if (ignoredReasons)
719 ignoredReasons->append(IgnoredReason(AXProbablyPresentational));
664 return true; 720 return true;
721 }
665 // Otherwise fall through; use presence of help text, title, or descript ion to decide. 722 // Otherwise fall through; use presence of help text, title, or descript ion to decide.
666 } 723 }
667 724
668 if (isWebArea() || m_layoutObject->isListMarker()) 725 if (isWebArea() || m_layoutObject->isListMarker())
669 return false; 726 return false;
670 727
671 // Using the help text, title or accessibility description (so we 728 // Using the help text, title or accessibility description (so we
672 // check if there's some kind of accessible name for the element) 729 // check if there's some kind of accessible name for the element)
673 // to decide an element's visibility is not as definitive as 730 // to decide an element's visibility is not as definitive as
674 // previous checks, so this should remain as one of the last. 731 // previous checks, so this should remain as one of the last.
675 // 732 //
676 // These checks are simplified in the interest of execution speed; 733 // These checks are simplified in the interest of execution speed;
677 // for example, any element having an alt attribute will make it 734 // for example, any element having an alt attribute will make it
678 // not ignored, rather than just images. 735 // not ignored, rather than just images.
679 if (!getAttribute(aria_helpAttr).isEmpty() || !getAttribute(aria_describedby Attr).isEmpty() || !getAttribute(altAttr).isEmpty() || !getAttribute(titleAttr). isEmpty()) 736 if (!getAttribute(aria_helpAttr).isEmpty() || !getAttribute(aria_describedby Attr).isEmpty() || !getAttribute(altAttr).isEmpty() || !getAttribute(titleAttr). isEmpty())
680 return false; 737 return false;
681 738
682 // Don't ignore generic focusable elements like <div tabindex=0> 739 // Don't ignore generic focusable elements like <div tabindex=0>
683 // unless they're completely empty, with no children. 740 // unless they're completely empty, with no children.
684 if (isGenericFocusableElement() && node->hasChildren()) 741 if (isGenericFocusableElement() && node->hasChildren())
685 return false; 742 return false;
686 743
687 if (!ariaAccessibilityDescription().isEmpty()) 744 if (!ariaAccessibilityDescription().isEmpty())
688 return false; 745 return false;
689 746
690 // By default, objects should be ignored so that the AX hierarchy is not 747 // By default, objects should be ignored so that the AX hierarchy is not
691 // filled with unnecessary items. 748 // filled with unnecessary items.
749 if (ignoredReasons)
750 ignoredReasons->append(IgnoredReason(AXUninteresting));
692 return true; 751 return true;
693 } 752 }
694 753
695 // 754 //
696 // Properties of static elements. 755 // Properties of static elements.
697 // 756 //
698 757
699 const AtomicString& AXLayoutObject::accessKey() const 758 const AtomicString& AXLayoutObject::accessKey() const
700 { 759 {
701 Node* node = m_layoutObject->node(); 760 Node* node = m_layoutObject->node();
(...skipping 1576 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 if (label && label->layoutObject()) { 2337 if (label && label->layoutObject()) {
2279 LayoutRect labelRect = axObjectCache()->getOrCreate(label)->elementR ect(); 2338 LayoutRect labelRect = axObjectCache()->getOrCreate(label)->elementR ect();
2280 result.unite(labelRect); 2339 result.unite(labelRect);
2281 } 2340 }
2282 } 2341 }
2283 2342
2284 return result; 2343 return result;
2285 } 2344 }
2286 2345
2287 } // namespace blink 2346 } // 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