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

Side by Side Diff: Source/modules/accessibility/AXObject.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: rebase 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008, 2009, 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2008, 2009, 2011 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 10 matching lines...) Expand all
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "config.h" 29 #include "config.h"
30 #include "modules/accessibility/AXObject.h" 30 #include "modules/accessibility/AXObject.h"
31 #include "core/dom/NodeTraversal.h" 31
32 #include "core/dom/LayoutTreeBuilderTraversal.h"
32 #include "core/editing/VisibleUnits.h" 33 #include "core/editing/VisibleUnits.h"
33 #include "core/editing/htmlediting.h" 34 #include "core/editing/htmlediting.h"
34 #include "core/frame/LocalFrame.h" 35 #include "core/frame/LocalFrame.h"
35 #include "core/frame/Settings.h" 36 #include "core/frame/Settings.h"
37 #include "core/html/HTMLDialogElement.h"
38 #include "core/html/HTMLFrameOwnerElement.h"
36 #include "core/layout/LayoutListItem.h" 39 #include "core/layout/LayoutListItem.h"
37 #include "core/layout/LayoutTheme.h" 40 #include "core/layout/LayoutTheme.h"
38 #include "core/layout/LayoutView.h" 41 #include "core/layout/LayoutView.h"
39 #include "modules/accessibility/AXObjectCacheImpl.h" 42 #include "modules/accessibility/AXObjectCacheImpl.h"
43 #include "modules/accessibility/InspectorTypeBuilderHelper.h"
40 #include "platform/UserGestureIndicator.h" 44 #include "platform/UserGestureIndicator.h"
41 #include "platform/text/PlatformLocale.h" 45 #include "platform/text/PlatformLocale.h"
42 #include "wtf/HashSet.h" 46 #include "wtf/HashSet.h"
43 #include "wtf/StdLibExtras.h" 47 #include "wtf/StdLibExtras.h"
44 #include "wtf/text/WTFString.h" 48 #include "wtf/text/WTFString.h"
45 49
46 using blink::WebLocalizedString; 50 using blink::WebLocalizedString;
47 51
48 namespace blink { 52 namespace blink {
49 53
50 using namespace HTMLNames; 54 using namespace HTMLNames;
51 55
56 using TypeBuilder::Accessibility::AXIgnoredReasons;
57 using TypeBuilder::Accessibility::AXNode;
58 using TypeBuilder::Accessibility::AXProperty;
59 using TypeBuilder::Accessibility::AXRelatedNode;
60 using TypeBuilder::Accessibility::AXValue;
61 using TypeBuilder::Accessibility::AXValueType;
62
52 namespace { 63 namespace {
53 typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap; 64 typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap;
54 typedef HashSet<String, CaseFoldingHash> ARIAWidgetSet; 65 typedef HashSet<String, CaseFoldingHash> ARIAWidgetSet;
55 66
56 struct RoleEntry { 67 struct RoleEntry {
57 const char* ariaRole; 68 const char* ariaRole;
58 AccessibilityRole webcoreRole; 69 AccessibilityRole webcoreRole;
59 }; 70 };
60 71
61 const RoleEntry roles[] = { 72 const RoleEntry roles[] = {
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 "aria-controls", 362 "aria-controls",
352 "aria-disabled", // If it's disabled, it can be made interactive. 363 "aria-disabled", // If it's disabled, it can be made interactive.
353 "aria-expanded", 364 "aria-expanded",
354 "aria-haspopup", 365 "aria-haspopup",
355 "aria-multiselectable", 366 "aria-multiselectable",
356 "aria-pressed", 367 "aria-pressed",
357 "aria-required", 368 "aria-required",
358 "aria-selected" 369 "aria-selected"
359 }; 370 };
360 371
372
373 HTMLDialogElement* getActiveDialogElement(Node* node)
374 {
375 HTMLDialogElement* dialog = node->document().activeModalDialog();
376 if (dialog && node != node->document() && !LayoutTreeBuilderTraversal::conta ins(*dialog, *node))
377 return dialog;
378 if (node->document().ownerElement())
379 return getActiveDialogElement(node->document().ownerElement());
380 return 0;
381 }
382
361 } // namespace 383 } // namespace
362 384
363 AXObject::AXObject(AXObjectCacheImpl* axObjectCache) 385 AXObject::AXObject(AXObjectCacheImpl* axObjectCache)
364 : m_id(0) 386 : m_id(0)
365 , m_haveChildren(false) 387 , m_haveChildren(false)
366 , m_role(UnknownRole) 388 , m_role(UnknownRole)
367 , m_lastKnownIsIgnoredValue(DefaultBehavior) 389 , m_lastKnownIsIgnoredValue(DefaultBehavior)
368 , m_detached(false) 390 , m_detached(false)
369 , m_parent(0) 391 , m_parent(0)
370 , m_lastModificationCount(-1) 392 , m_lastModificationCount(-1)
371 , m_cachedIsIgnored(false) 393 , m_cachedIsIgnored(false)
372 , m_cachedIsInertOrAriaHidden(false) 394 , m_cachedIsInertOrAriaHidden(false)
373 , m_cachedIsDescendantOfBarrenParent(false) 395 , m_cachedIsDescendantOfLeafNode(false)
374 , m_cachedIsDescendantOfDisabledNode(false) 396 , m_cachedIsDescendantOfDisabledNode(false)
375 , m_cachedHasInheritedPresentationalRole(false) 397 , m_cachedHasInheritedPresentationalRole(false)
376 , m_cachedLiveRegionRoot(0) 398 , m_cachedLiveRegionRoot(0)
377 , m_axObjectCache(axObjectCache) 399 , m_axObjectCache(axObjectCache)
378 { 400 {
379 } 401 }
380 402
381 AXObject::~AXObject() 403 AXObject::~AXObject()
382 { 404 {
383 ASSERT(isDetached()); 405 ASSERT(isDetached());
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 { 520 {
499 AXObjectCacheImpl* cache = axObjectCache(); 521 AXObjectCacheImpl* cache = axObjectCache();
500 if (!cache) 522 if (!cache)
501 return; 523 return;
502 524
503 if (cache->modificationCount() == m_lastModificationCount) 525 if (cache->modificationCount() == m_lastModificationCount)
504 return; 526 return;
505 527
506 m_lastModificationCount = cache->modificationCount(); 528 m_lastModificationCount = cache->modificationCount();
507 m_cachedIsInertOrAriaHidden = computeIsInertOrAriaHidden(); 529 m_cachedIsInertOrAriaHidden = computeIsInertOrAriaHidden();
508 m_cachedIsDescendantOfBarrenParent = computeIsDescendantOfBarrenParent(); 530 m_cachedIsDescendantOfLeafNode = (leafNodeAncestor() != 0);
509 m_cachedIsDescendantOfDisabledNode = computeIsDescendantOfDisabledNode(); 531 m_cachedIsDescendantOfDisabledNode = (disabledAncestor() != 0);
510 m_cachedHasInheritedPresentationalRole = computeHasInheritedPresentationalRo le(); 532 m_cachedHasInheritedPresentationalRole = (inheritsPresentationalRoleFrom() ! = 0);
511 m_cachedIsIgnored = computeAccessibilityIsIgnored(); 533 m_cachedIsIgnored = computeAccessibilityIsIgnored();
512 m_cachedLiveRegionRoot = isLiveRegion() ? 534 m_cachedLiveRegionRoot = isLiveRegion() ?
513 this : 535 this :
514 (parentObjectIfExists() ? parentObjectIfExists()->liveRegionRoot() : 0); 536 (parentObjectIfExists() ? parentObjectIfExists()->liveRegionRoot() : 0);
515 } 537 }
516 538
517 bool AXObject::accessibilityIsIgnoredByDefault() const 539 bool AXObject::accessibilityIsIgnoredByDefault(PassRefPtr<TypeBuilder::Array<Typ eBuilder::Accessibility::AXProperty>> passIgnoredReasons) const
518 { 540 {
519 return defaultObjectInclusion() == IgnoreObject; 541 return defaultObjectInclusion(passIgnoredReasons) == IgnoreObject;
520 } 542 }
521 543
522 AXObjectInclusion AXObject::accessibilityPlatformIncludesObject() const 544 AXObjectInclusion AXObject::accessibilityPlatformIncludesObject() const
523 { 545 {
524 if (isMenuListPopup() || isMenuListOption()) 546 if (isMenuListPopup() || isMenuListOption())
525 return IncludeObject; 547 return IncludeObject;
526 548
527 return DefaultBehavior; 549 return DefaultBehavior;
528 } 550 }
529 551
530 AXObjectInclusion AXObject::defaultObjectInclusion() const 552 AXObjectInclusion AXObject::defaultObjectInclusion(PassRefPtr<TypeBuilder::Array <TypeBuilder::Accessibility::AXProperty>> passIgnoredReasons) const
531 { 553 {
532 if (isInertOrAriaHidden()) 554 RefPtr<TypeBuilder::Array<TypeBuilder::Accessibility::AXProperty>> ignoredRe asons = passIgnoredReasons;
555
556 if (isInertOrAriaHidden()) {
557 if (ignoredReasons)
558 computeIsInertOrAriaHidden(ignoredReasons);
533 return IgnoreObject; 559 return IgnoreObject;
560 }
534 561
535 if (isPresentationalChildOfAriaRole()) 562 if (AXObject* ancestor = ancestorForWhichThisIsAPresentationalChild()) {
563 if (ignoredReasons)
564 ignoredReasons->addItem(createProperty(AXIgnoredReasons::AncestorDis allowsChild, createRelatedNodeValue(ancestor)));
536 return IgnoreObject; 565 return IgnoreObject;
566 }
537 567
538 return accessibilityPlatformIncludesObject(); 568 return accessibilityPlatformIncludesObject();
539 } 569 }
540 570
541 bool AXObject::isInertOrAriaHidden() const 571 bool AXObject::isInertOrAriaHidden() const
542 { 572 {
543 updateCachedAttributeValuesIfNeeded(); 573 updateCachedAttributeValuesIfNeeded();
544 return m_cachedIsInertOrAriaHidden; 574 return m_cachedIsInertOrAriaHidden;
545 } 575 }
546 576
547 bool AXObject::computeIsInertOrAriaHidden() const 577 bool AXObject::computeIsInertOrAriaHidden(PassRefPtr<TypeBuilder::Array<TypeBuil der::Accessibility::AXProperty>> passIgnoredReasons) const
548 { 578 {
579 RefPtr<TypeBuilder::Array<TypeBuilder::Accessibility::AXProperty>> ignoredRe asons = passIgnoredReasons;
580
549 if (node()) { 581 if (node()) {
550 if (node()->isInert()) 582 if (node()->isInert()) {
583 if (ignoredReasons) {
584 HTMLDialogElement* dialog = getActiveDialogElement(node());
585 if (dialog) {
586 AXObject* dialogObject = axObjectCache()->getOrCreate(dialog );
587 if (dialogObject)
588 ignoredReasons->addItem(createProperty(AXIgnoredReasons: :ActiveModalDialog, createRelatedNodeValue(dialogObject)));
589 }
dmazzoni 2015/04/15 17:00:02 Handle the else case? In the future there may be
aboxhall 2015/04/15 17:55:46 But it'll be due to an inert attribute somewhere,
590 }
551 return true; 591 return true;
592 }
552 } else { 593 } else {
553 AXObject* parent = parentObject(); 594 AXObject* parent = parentObject();
554 if (parent && parent->isInertOrAriaHidden()) 595 if (parent && parent->isInertOrAriaHidden()) {
596 if (ignoredReasons)
597 parent->computeIsInertOrAriaHidden(ignoredReasons);
555 return true; 598 return true;
599 }
556 } 600 }
557 601
558 return ariaHiddenRoot() != 0; 602 const AXObject* hiddenRoot = ariaHiddenRoot();
559 } 603 if (hiddenRoot) {
560 604 if (ignoredReasons) {
561 bool AXObject::isDescendantOfBarrenParent() const 605 if (hiddenRoot == this)
562 { 606 ignoredReasons->addItem(createProperty(AXIgnoredReasons::AriaHid den, createBooleanValue(true)));
563 updateCachedAttributeValuesIfNeeded(); 607 else
564 return m_cachedIsDescendantOfBarrenParent; 608 ignoredReasons->addItem(createProperty(AXIgnoredReasons::AriaHid denRoot, createRelatedNodeValue(hiddenRoot)));
565 } 609 }
566 610 return true;
567 bool AXObject::computeIsDescendantOfBarrenParent() const
568 {
569 if (AXObject* parent = parentObject()) {
570 if (!parent->canHaveChildren())
571 return true;
572
573 return parent->isDescendantOfBarrenParent();
574 } 611 }
575 612
576 return false; 613 return false;
577 } 614 }
578 615
616 bool AXObject::isDescendantOfLeafNode() const
617 {
618 updateCachedAttributeValuesIfNeeded();
619 return m_cachedIsDescendantOfLeafNode;
620 }
621
622 AXObject* AXObject::leafNodeAncestor() const
623 {
624 if (AXObject* parent = parentObject()) {
625 if (!parent->canHaveChildren())
626 return parent;
627
628 return parent->leafNodeAncestor();
629 }
630
631 return 0;
632 }
633
579 const AXObject* AXObject::ariaHiddenRoot() const 634 const AXObject* AXObject::ariaHiddenRoot() const
580 { 635 {
581 for (const AXObject* object = this; object; object = object->parentObject()) { 636 for (const AXObject* object = this; object; object = object->parentObject()) {
582 if (equalIgnoringCase(object->getAttribute(aria_hiddenAttr), "true")) 637 if (equalIgnoringCase(object->getAttribute(aria_hiddenAttr), "true"))
583 return object; 638 return object;
584 } 639 }
585 640
586 return 0; 641 return 0;
587 } 642 }
588 643
589 bool AXObject::isDescendantOfDisabledNode() const 644 bool AXObject::isDescendantOfDisabledNode() const
590 { 645 {
591 updateCachedAttributeValuesIfNeeded(); 646 updateCachedAttributeValuesIfNeeded();
592 return m_cachedIsDescendantOfDisabledNode; 647 return m_cachedIsDescendantOfDisabledNode;
593 } 648 }
594 649
595 bool AXObject::computeIsDescendantOfDisabledNode() const 650 const AXObject* AXObject::disabledAncestor() const
596 { 651 {
597 const AtomicString& disabled = getAttribute(aria_disabledAttr); 652 const AtomicString& disabled = getAttribute(aria_disabledAttr);
598 if (equalIgnoringCase(disabled, "true")) 653 if (equalIgnoringCase(disabled, "true"))
599 return true; 654 return this;
600 if (equalIgnoringCase(disabled, "false")) 655 if (equalIgnoringCase(disabled, "false"))
601 return false; 656 return 0;
602 657
603 if (AXObject* parent = parentObject()) 658 if (AXObject* parent = parentObject())
604 return parent->isDescendantOfDisabledNode(); 659 return parent->disabledAncestor();
605 660
606 return false; 661 return 0;
607 } 662 }
608 663
609 bool AXObject::lastKnownIsIgnoredValue() 664 bool AXObject::lastKnownIsIgnoredValue()
610 { 665 {
611 if (m_lastKnownIsIgnoredValue == DefaultBehavior) 666 if (m_lastKnownIsIgnoredValue == DefaultBehavior)
612 m_lastKnownIsIgnoredValue = accessibilityIsIgnored() ? IgnoreObject : In cludeObject; 667 m_lastKnownIsIgnoredValue = accessibilityIsIgnored() ? IgnoreObject : In cludeObject;
613 668
614 return m_lastKnownIsIgnoredValue == IgnoreObject; 669 return m_lastKnownIsIgnoredValue == IgnoreObject;
615 } 670 }
616 671
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after
1299 } 1354 }
1300 1355
1301 const AtomicString& AXObject::internalRoleName(AccessibilityRole role) 1356 const AtomicString& AXObject::internalRoleName(AccessibilityRole role)
1302 { 1357 {
1303 static const Vector<AtomicString>* internalRoleNameVector = createInternalRo leNameVector(); 1358 static const Vector<AtomicString>* internalRoleNameVector = createInternalRo leNameVector();
1304 1359
1305 return internalRoleNameVector->at(role); 1360 return internalRoleNameVector->at(role);
1306 } 1361 }
1307 1362
1308 } // namespace blink 1363 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698