Chromium Code Reviews| Index: Source/modules/accessibility/AXLayoutObject.cpp |
| diff --git a/Source/modules/accessibility/AXLayoutObject.cpp b/Source/modules/accessibility/AXLayoutObject.cpp |
| index 7f100c1271312000019fbb27417d78c37303d96d..b1f9e6de07da523a46259d2171ab9238f475f61e 100644 |
| --- a/Source/modules/accessibility/AXLayoutObject.cpp |
| +++ b/Source/modules/accessibility/AXLayoutObject.cpp |
| @@ -45,6 +45,10 @@ |
| #include "core/html/HTMLLabelElement.h" |
| #include "core/html/HTMLOptionElement.h" |
| #include "core/html/HTMLSelectElement.h" |
| +#include "core/html/HTMLTableCellElement.h" |
| +#include "core/html/HTMLTableElement.h" |
| +#include "core/html/HTMLTableRowElement.h" |
| +#include "core/html/HTMLTableSectionElement.h" |
| #include "core/html/HTMLTextAreaElement.h" |
| #include "core/html/shadow/ShadowElementNames.h" |
| #include "core/layout/HitTestResult.h" |
| @@ -171,6 +175,7 @@ AXLayoutObject::AXLayoutObject(LayoutObject* layoutObject, AXObjectCacheImpl* ax |
| : AXNodeObject(layoutObject->node(), axObjectCache) |
| , m_layoutObject(layoutObject) |
| , m_cachedElementRectDirty(true) |
| + , m_hasInheritedPresentationRole(false) |
| { |
| #if ENABLE(ASSERT) |
| m_layoutObject->setHasAXObject(true); |
| @@ -546,6 +551,7 @@ bool AXLayoutObject::computeAccessibilityIsIgnored() const |
| #if ENABLE(ASSERT) |
| ASSERT(m_initialized); |
| #endif |
| + m_hasInheritedPresentationRole = false; |
| // Check first if any of the common reasons cause this element to be ignored. |
| // Then process other use cases that need to be applied to all the various roles |
| @@ -563,7 +569,12 @@ bool AXLayoutObject::computeAccessibilityIsIgnored() const |
| if (roleValue() == IgnoredRole) |
| return true; |
| - if ((roleValue() == NoneRole || roleValue() == PresentationalRole) || inheritsPresentationalRole()) |
| + if (roleValue() == NoneRole || roleValue() == PresentationalRole) { |
| + m_hasInheritedPresentationRole = true; |
|
dmazzoni
2015/03/29 07:46:22
I don't want to compute this inside computeAccessi
je_julie(Not used)
2015/03/31 16:14:27
I added computeHasInheritedPresentationRole.
|
| + return true; |
| + } |
| + |
| + if (inheritsPresentationalRole()) |
| return true; |
| // An ARIA tree can only have tree items and static text as children. |
| @@ -2328,27 +2339,90 @@ bool AXLayoutObject::inheritsPresentationalRole() const |
| if (canSetFocusAttribute()) |
| return false; |
| - // ARIA spec says that when a parent object is presentational, and it has required child elements, |
| - // those child elements are also presentational. For example, <li> becomes presentational from <ul>. |
| - // http://www.w3.org/WAI/PF/aria/complete#presentation |
| - if (roleValue() != ListItemRole && roleValue() != ListMarkerRole) |
| + // http://www.w3.org/TR/wai-aria/complete#presentation |
| + // ARIA spec says that the user agent MUST apply an inherited role of presentation |
| + // to any owned elements that do not have an explicit role defined. |
| + if (ariaRoleAttribute() != UnknownRole) |
| return false; |
| AXObject* parent = parentObject(); |
| - if (!parent->isAXLayoutObject()) |
| + if (!parent) |
| return false; |
| - Node* elementNode = toAXLayoutObject(parent)->node(); |
| - if (!elementNode || !elementNode->isElementNode()) |
| + // The parent should have presentationalRole. |
| + if (!isPresentationRole(parent) && !isPresentationRoleInTable(parent)) |
| + return false; |
| + |
| + // ARIA spec says that when a parent object is presentational, and it has required owned elements, |
| + // those elements are also presentational. For example, <li> becomes presentational from <ul>. |
| + return m_hasInheritedPresentationRole = isRequiredOwnedElement(parent); |
| +} |
| + |
| +bool AXLayoutObject::isRequiredOwnedElement(AXObject* parent) const |
| +{ |
| + if (!parent->isAXLayoutObject()) |
| return false; |
| - QualifiedName tagName = toElement(elementNode)->tagQName(); |
| - if (tagName != ulTag && tagName != olTag && tagName != dlTag) |
| + Node* parentNode = toAXLayoutObject(parent)->node(); |
| + if (!parentNode || !parentNode->isElementNode()) |
| return false; |
| - if (parent->roleValue() == NoneRole || parent->roleValue() == PresentationalRole) |
| - return ariaRoleAttribute() == UnknownRole; |
| + AccessibilityRole role = roleValue(); |
| + |
| + if (role == ListItemRole) |
| + return isListElement(parentNode); |
| + if (role == ListMarkerRole) |
| + return isHTMLLIElement(*parentNode); |
| + if (role == MenuItemCheckBoxRole || role == MenuItemRole || role == MenuItemRadioRole) |
| + return isHTMLMenuElement(*parentNode); |
| + |
| + Node* curNode = node(); |
| + if (isHTMLTableCellElement(curNode)) |
| + return isHTMLTableRowElement(*parentNode); |
| + if (isHTMLTableRowElement(curNode)) |
| + return isHTMLTableSectionElement(*parentNode); |
| + |
| + // In case of ListboxRole and it's child, ListBoxOptionRole, |
| + // Inheritance of presentation role is handled in AXListBoxOption |
| + // Because ListBoxOption Role doesn't have any child. |
| + // If it's just ignored because of presentation, we can't see any AX tree related to ListBoxOption. |
| + return false; |
| +} |
| + |
| +bool AXLayoutObject::isListElement(Node* node) const |
| +{ |
| + return isHTMLUListElement(*node) || isHTMLOListElement(*node) || isHTMLDListElement(*node); |
| +} |
| + |
| +bool AXLayoutObject::isPresentationRole(AXObject* parent) const |
| +{ |
| + return parent->roleValue() == NoneRole || parent->roleValue() == PresentationalRole |
| + || parent->hasInheritedPresentationRole(); |
| +} |
| + |
| +bool AXLayoutObject::isPresentationRoleInTable(AXObject* parent) const |
| +{ |
| + Node* parentNode = parent->node(); |
| + if (!parentNode || !parentNode->isElementNode()) |
| + return false; |
| + Node* curNode = node(); |
| + // AXTable determines the role as checking isTableXXX. |
| + // If Table has explicit role including presentation, AXTable doesn't assign implicit Role |
| + // to a whole Table. That's why we should check it based on node. |
| + // Normal Table Tree is that |
| + // cell(its role)-> tr(tr role)-> tfoot, tbody, thead(ignored role) -> table(table role). |
| + // If table has presentation role, it will be like |
| + // cell(group)-> tr(unknown) -> tfoot, tbody, thead(ignored) -> table(presentation). |
| + if (isHTMLTableCellElement(curNode) && isHTMLTableRowElement(*parentNode)) |
| + return parent->hasInheritedPresentationRole(); |
| + |
| + if (isHTMLTableRowElement(curNode) && isHTMLTableSectionElement(*parentNode)) { |
| + // Because TableSections have ignored role, presentation should be checked with its parent node |
| + AXObject* tableObject = parent->parentObject(); |
| + Node* tableNode = tableObject->node(); |
| + return isHTMLTableElement(tableNode) && tableObject->hasInheritedPresentationRole(); |
| + } |
| return false; |
| } |