Chromium Code Reviews| Index: Source/modules/accessibility/AXObject.cpp |
| diff --git a/Source/modules/accessibility/AXObject.cpp b/Source/modules/accessibility/AXObject.cpp |
| index e05a796356d47388e2b9ba1dfd4e4a83316fcee2..c1f590e7103be5f779c8a71af532d863eb1013e1 100644 |
| --- a/Source/modules/accessibility/AXObject.cpp |
| +++ b/Source/modules/accessibility/AXObject.cpp |
| @@ -28,15 +28,19 @@ |
| #include "config.h" |
| #include "modules/accessibility/AXObject.h" |
| -#include "core/dom/NodeTraversal.h" |
| + |
| +#include "core/dom/LayoutTreeBuilderTraversal.h" |
| #include "core/editing/VisibleUnits.h" |
| #include "core/editing/htmlediting.h" |
| #include "core/frame/LocalFrame.h" |
| #include "core/frame/Settings.h" |
| +#include "core/html/HTMLDialogElement.h" |
| +#include "core/html/HTMLFrameOwnerElement.h" |
| #include "core/layout/LayoutListItem.h" |
| #include "core/layout/LayoutTheme.h" |
| #include "core/layout/LayoutView.h" |
| #include "modules/accessibility/AXObjectCacheImpl.h" |
| +#include "modules/accessibility/InspectorTypeBuilderHelper.h" |
| #include "platform/UserGestureIndicator.h" |
| #include "platform/text/PlatformLocale.h" |
| #include "wtf/HashSet.h" |
| @@ -49,6 +53,13 @@ namespace blink { |
| using namespace HTMLNames; |
| +using TypeBuilder::Accessibility::AXIgnoredReasons; |
| +using TypeBuilder::Accessibility::AXNode; |
| +using TypeBuilder::Accessibility::AXProperty; |
| +using TypeBuilder::Accessibility::AXRelatedNode; |
| +using TypeBuilder::Accessibility::AXValue; |
| +using TypeBuilder::Accessibility::AXValueType; |
| + |
| namespace { |
| typedef HashMap<String, AccessibilityRole, CaseFoldingHash> ARIARoleMap; |
| typedef HashSet<String, CaseFoldingHash> ARIAWidgetSet; |
| @@ -358,6 +369,17 @@ const char* ariaInteractiveWidgetAttributes[] = { |
| "aria-selected" |
| }; |
| + |
| +HTMLDialogElement* getActiveDialogElement(Node* node) |
| +{ |
| + HTMLDialogElement* dialog = node->document().activeModalDialog(); |
| + if (dialog && node != node->document() && !LayoutTreeBuilderTraversal::contains(*dialog, *node)) |
| + return dialog; |
| + if (node->document().ownerElement()) |
| + return getActiveDialogElement(node->document().ownerElement()); |
| + return 0; |
| +} |
| + |
| } // namespace |
| AXObject::AXObject(AXObjectCacheImpl* axObjectCache) |
| @@ -370,7 +392,7 @@ AXObject::AXObject(AXObjectCacheImpl* axObjectCache) |
| , m_lastModificationCount(-1) |
| , m_cachedIsIgnored(false) |
| , m_cachedIsInertOrAriaHidden(false) |
| - , m_cachedIsDescendantOfBarrenParent(false) |
| + , m_cachedIsDescendantOfLeafNode(false) |
| , m_cachedIsDescendantOfDisabledNode(false) |
| , m_cachedHasInheritedPresentationalRole(false) |
| , m_cachedLiveRegionRoot(0) |
| @@ -505,18 +527,18 @@ void AXObject::updateCachedAttributeValuesIfNeeded() const |
| m_lastModificationCount = cache->modificationCount(); |
| m_cachedIsInertOrAriaHidden = computeIsInertOrAriaHidden(); |
| - m_cachedIsDescendantOfBarrenParent = computeIsDescendantOfBarrenParent(); |
| - m_cachedIsDescendantOfDisabledNode = computeIsDescendantOfDisabledNode(); |
| - m_cachedHasInheritedPresentationalRole = computeHasInheritedPresentationalRole(); |
| + m_cachedIsDescendantOfLeafNode = (leafNodeAncestor() != 0); |
| + m_cachedIsDescendantOfDisabledNode = (disabledAncestor() != 0); |
| + m_cachedHasInheritedPresentationalRole = (inheritsPresentationalRoleFrom() != 0); |
| m_cachedIsIgnored = computeAccessibilityIsIgnored(); |
| m_cachedLiveRegionRoot = isLiveRegion() ? |
| this : |
| (parentObjectIfExists() ? parentObjectIfExists()->liveRegionRoot() : 0); |
| } |
| -bool AXObject::accessibilityIsIgnoredByDefault() const |
| +bool AXObject::accessibilityIsIgnoredByDefault(PassRefPtr<TypeBuilder::Array<TypeBuilder::Accessibility::AXProperty>> passIgnoredReasons) const |
| { |
| - return defaultObjectInclusion() == IgnoreObject; |
| + return defaultObjectInclusion(passIgnoredReasons) == IgnoreObject; |
| } |
| AXObjectInclusion AXObject::accessibilityPlatformIncludesObject() const |
| @@ -527,13 +549,21 @@ AXObjectInclusion AXObject::accessibilityPlatformIncludesObject() const |
| return DefaultBehavior; |
| } |
| -AXObjectInclusion AXObject::defaultObjectInclusion() const |
| +AXObjectInclusion AXObject::defaultObjectInclusion(PassRefPtr<TypeBuilder::Array<TypeBuilder::Accessibility::AXProperty>> passIgnoredReasons) const |
| { |
| - if (isInertOrAriaHidden()) |
| + RefPtr<TypeBuilder::Array<TypeBuilder::Accessibility::AXProperty>> ignoredReasons = passIgnoredReasons; |
| + |
| + if (isInertOrAriaHidden()) { |
| + if (ignoredReasons) |
| + computeIsInertOrAriaHidden(ignoredReasons); |
| return IgnoreObject; |
| + } |
| - if (isPresentationalChildOfAriaRole()) |
| + if (AXObject* ancestor = ancestorForWhichThisIsAPresentationalChild()) { |
| + if (ignoredReasons) |
| + ignoredReasons->addItem(createProperty(AXIgnoredReasons::AncestorDisallowsChild, createRelatedNodeValue(ancestor))); |
| return IgnoreObject; |
| + } |
| return accessibilityPlatformIncludesObject(); |
| } |
| @@ -544,36 +574,61 @@ bool AXObject::isInertOrAriaHidden() const |
| return m_cachedIsInertOrAriaHidden; |
| } |
| -bool AXObject::computeIsInertOrAriaHidden() const |
| +bool AXObject::computeIsInertOrAriaHidden(PassRefPtr<TypeBuilder::Array<TypeBuilder::Accessibility::AXProperty>> passIgnoredReasons) const |
| { |
| + RefPtr<TypeBuilder::Array<TypeBuilder::Accessibility::AXProperty>> ignoredReasons = passIgnoredReasons; |
| + |
| if (node()) { |
| - if (node()->isInert()) |
| + if (node()->isInert()) { |
| + if (ignoredReasons) { |
| + HTMLDialogElement* dialog = getActiveDialogElement(node()); |
| + if (dialog) { |
| + AXObject* dialogObject = axObjectCache()->getOrCreate(dialog); |
| + if (dialogObject) |
| + ignoredReasons->addItem(createProperty(AXIgnoredReasons::ActiveModalDialog, createRelatedNodeValue(dialogObject))); |
| + } |
|
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,
|
| + } |
| return true; |
| + } |
| } else { |
| AXObject* parent = parentObject(); |
| - if (parent && parent->isInertOrAriaHidden()) |
| + if (parent && parent->isInertOrAriaHidden()) { |
| + if (ignoredReasons) |
| + parent->computeIsInertOrAriaHidden(ignoredReasons); |
| return true; |
| + } |
| } |
| - return ariaHiddenRoot() != 0; |
| + const AXObject* hiddenRoot = ariaHiddenRoot(); |
| + if (hiddenRoot) { |
| + if (ignoredReasons) { |
| + if (hiddenRoot == this) |
| + ignoredReasons->addItem(createProperty(AXIgnoredReasons::AriaHidden, createBooleanValue(true))); |
| + else |
| + ignoredReasons->addItem(createProperty(AXIgnoredReasons::AriaHiddenRoot, createRelatedNodeValue(hiddenRoot))); |
| + } |
| + return true; |
| + } |
| + |
| + return false; |
| } |
| -bool AXObject::isDescendantOfBarrenParent() const |
| +bool AXObject::isDescendantOfLeafNode() const |
| { |
| updateCachedAttributeValuesIfNeeded(); |
| - return m_cachedIsDescendantOfBarrenParent; |
| + return m_cachedIsDescendantOfLeafNode; |
| } |
| -bool AXObject::computeIsDescendantOfBarrenParent() const |
| +AXObject* AXObject::leafNodeAncestor() const |
| { |
| if (AXObject* parent = parentObject()) { |
| if (!parent->canHaveChildren()) |
| - return true; |
| + return parent; |
| - return parent->isDescendantOfBarrenParent(); |
| + return parent->leafNodeAncestor(); |
| } |
| - return false; |
| + return 0; |
| } |
| const AXObject* AXObject::ariaHiddenRoot() const |
| @@ -592,18 +647,18 @@ bool AXObject::isDescendantOfDisabledNode() const |
| return m_cachedIsDescendantOfDisabledNode; |
| } |
| -bool AXObject::computeIsDescendantOfDisabledNode() const |
| +const AXObject* AXObject::disabledAncestor() const |
| { |
| const AtomicString& disabled = getAttribute(aria_disabledAttr); |
| if (equalIgnoringCase(disabled, "true")) |
| - return true; |
| + return this; |
| if (equalIgnoringCase(disabled, "false")) |
| - return false; |
| + return 0; |
| if (AXObject* parent = parentObject()) |
| - return parent->isDescendantOfDisabledNode(); |
| + return parent->disabledAncestor(); |
| - return false; |
| + return 0; |
| } |
| bool AXObject::lastKnownIsIgnoredValue() |