diff --git a/accessible/base/nsAccessibilityService.cpp b/accessible/base/nsAccessibilityService.cpp index 9414d6d13916..bc51ad74880b 100644 --- a/accessible/base/nsAccessibilityService.cpp +++ b/accessible/base/nsAccessibilityService.cpp @@ -103,15 +103,49 @@ using namespace mozilla::dom; //////////////////////////////////////////////////////////////////////////////// /** - * Return true if the element must be accessible. + * Return true if the role map entry is an ARIA table part. */ -static bool MustBeAccessible(nsIContent* aContent, DocAccessible* aDocument) { - nsIFrame* frame = aContent->GetPrimaryFrame(); - MOZ_ASSERT(frame); - if (frame->IsFocusable()) { - return true; - } +static bool IsARIATablePart(const nsRoleMapEntry* aRoleMapEntry) { + return aRoleMapEntry && + (aRoleMapEntry->accTypes & (eTableCell | eTableRow | eTable)); +} +/** + * Create and return an Accessible for the given content depending on which + * table part we think it is. + */ +static LocalAccessible* CreateARIATablePartAcc( + const nsRoleMapEntry* aRoleMapEntry, const LocalAccessible* aContext, + nsIContent* aContent, DocAccessible* aDocument) { + // In case of ARIA grid or table use table-specific classes if it's not + // native table based. + if ((aRoleMapEntry->accTypes & eTableCell)) { + if (aContext->IsTableRow()) { + return new ARIAGridCellAccessible(aContent, aDocument); + } + } else if (aRoleMapEntry->IsOfType(eTableRow)) { + if (aContext->IsTable() || + // There can be an Accessible between a row and its table, but it + // can only be a row group or a generic container. This is + // consistent with Filters::GetRow and CachedTableAccessible's + // TablePartRule. + ((aContext->Role() == roles::GROUPING || + (aContext->IsGenericHyperText() && !aContext->ARIARoleMap())) && + aContext->LocalParent() && aContext->LocalParent()->IsTable())) { + return new ARIARowAccessible(aContent, aDocument); + } + } else if (aRoleMapEntry->IsOfType(eTable)) { + return new ARIAGridAccessible(aContent, aDocument); + } + return nullptr; +} + +/** + * Return true if the element has an attribute (ARIA, title, or relation) that + * requires the creation of an Accessible for the element. + */ +static bool AttributesMustBeAccessible(nsIContent* aContent, + DocAccessible* aDocument) { if (aContent->IsElement()) { uint32_t attrCount = aContent->AsElement()->GetAttrCount(); for (uint32_t attrIdx = 0; attrIdx < attrCount; attrIdx++) { @@ -138,7 +172,7 @@ static bool MustBeAccessible(nsIContent* aContent, DocAccessible* aDocument) { } // If the given ID is referred by relation attribute then create an - // accessible for it. + // Accessible for it. nsAutoString id; if (nsCoreUtils::GetID(aContent, id) && !id.IsEmpty()) { return aDocument->IsDependentID(aContent->AsElement(), id); @@ -176,6 +210,19 @@ static bool MustBeGenericAccessible(nsIContent* aContent, nsLayoutUtils::IsReallyFixedPos(frame))); } +/** + * Return true if the element must be accessible. + */ +static bool MustBeAccessible(nsIContent* aContent, DocAccessible* aDocument) { + nsIFrame* frame = aContent->GetPrimaryFrame(); + MOZ_ASSERT(frame); + if (frame->IsFocusable()) { + return true; + } + + return AttributesMustBeAccessible(aContent, aDocument); +} + bool nsAccessibilityService::ShouldCreateImgAccessible( mozilla::dom::Element* aElement, DocAccessible* aDocument) { // The element must have a layout frame for us to proceed. If there is no @@ -1022,16 +1069,41 @@ LocalAccessible* nsAccessibilityService::CreateAccessible( // display:contents element doesn't have a frame, but retains the // semantics. All its children are unaffected. const MarkupMapInfo* markupMap = GetMarkupMapInfoFor(content); + RefPtr newAcc; if (markupMap && markupMap->new_func) { - RefPtr newAcc = - markupMap->new_func(content->AsElement(), aContext); - if (newAcc) { - document->BindToDocument(newAcc, - aria::GetRoleMap(content->AsElement())); - } - return newAcc; + newAcc = markupMap->new_func(content->AsElement(), aContext); } - return nullptr; + + // Check whether this element has an ARIA role or attribute that requires + // us to create an Accessible. + const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(content->AsElement()); + const bool hasNonPresentationalARIARole = + roleMapEntry && !roleMapEntry->Is(nsGkAtoms::presentation) && + !roleMapEntry->Is(nsGkAtoms::none); + if (!newAcc && (hasNonPresentationalARIARole || + AttributesMustBeAccessible(content, document))) { + // If this element is an ARIA table part, create the proper table part + // Accessible. Otherwise, create a generic HyperTextAccessible. + if (IsARIATablePart(roleMapEntry)) { + newAcc = + CreateARIATablePartAcc(roleMapEntry, aContext, content, document); + } else { + newAcc = new HyperTextAccessibleWrap(content, document); + } + } + + // If there's still no Accessible but we do have an entry in the markup + // map for this non-presentational element, create a generic + // HyperTextAccessible. + if (!newAcc && markupMap && + (!roleMapEntry || hasNonPresentationalARIARole)) { + newAcc = new HyperTextAccessibleWrap(content, document); + } + + if (newAcc) { + document->BindToDocument(newAcc, roleMapEntry); + } + return newAcc; } else { if (aIsSubtreeHidden) { *aIsSubtreeHidden = true; @@ -1152,8 +1224,7 @@ LocalAccessible* nsAccessibilityService::CreateAccessible( } if (!newAcc && content->IsHTMLElement()) { // HTML accessibles - bool isARIATablePart = roleMapEntry && (roleMapEntry->accTypes & - (eTableCell | eTableRow | eTable)); + const bool isARIATablePart = IsARIATablePart(roleMapEntry); if (!isARIATablePart || frame->AccessibleType() == eHTMLTableCellType || frame->AccessibleType() == eHTMLTableRowType || @@ -1177,25 +1248,9 @@ LocalAccessible* nsAccessibilityService::CreateAccessible( // In case of ARIA grid or table use table-specific classes if it's not // native table based. if (isARIATablePart && (!newAcc || newAcc->IsGenericHyperText())) { - if ((roleMapEntry->accTypes & eTableCell)) { - if (aContext->IsTableRow()) { - newAcc = new ARIAGridCellAccessible(content, document); - } - - } else if (roleMapEntry->IsOfType(eTableRow)) { - if (aContext->IsTable() || - // There can be an Accessible between a row and its table, but it - // can only be a row group or a generic container. This is - // consistent with Filters::GetRow and CachedTableAccessible's - // TablePartRule. - ((aContext->Role() == roles::GROUPING || - (aContext->IsGenericHyperText() && !aContext->ARIARoleMap())) && - aContext->LocalParent() && aContext->LocalParent()->IsTable())) { - newAcc = new ARIARowAccessible(content, document); - } - - } else if (roleMapEntry->IsOfType(eTable)) { - newAcc = new ARIAGridAccessible(content, document); + if (LocalAccessible* tablePartAcc = CreateARIATablePartAcc( + roleMapEntry, aContext, content, document)) { + newAcc = tablePartAcc; } } diff --git a/accessible/tests/mochitest/tree/a11y.ini b/accessible/tests/mochitest/tree/a11y.ini index a1a71ed74ce7..c2a78c76a7e8 100644 --- a/accessible/tests/mochitest/tree/a11y.ini +++ b/accessible/tests/mochitest/tree/a11y.ini @@ -11,6 +11,7 @@ support-files = [test_applicationacc.xhtml] skip-if = true # Bug 561508 +[test_aria_display_contents.html] [test_aria_globals.html] [test_aria_grid.html] [test_aria_imgmap.html] diff --git a/accessible/tests/mochitest/tree/test_aria_display_contents.html b/accessible/tests/mochitest/tree/test_aria_display_contents.html new file mode 100644 index 000000000000..5c6f7f20fbb5 --- /dev/null +++ b/accessible/tests/mochitest/tree/test_aria_display_contents.html @@ -0,0 +1,173 @@ + + + + ARIA and style="display: contents;" + + + + + + + + + + + + + Mozilla Bug 1494196 + +

+ +
+  
+ +
+
+
col1
+
col2
+
+
+
row1
+
cell1
+
+
+
+
+
col1
+
col2
+
+
+
row1
+
cell1
+
+
+
+
+
col1
+
col2
+
+
+
row1
+
cell1
+
+
+
+
+
col1
+
col2
+
+
+
row1
+
cell1
+
+
+
+
+
col1
+
col2
+
+
+
row1
+
cell1
+
+
+
+
+
col1
+
col2
+
+
+
row1
+
cell1
+
+
+ +
+
+
test
+
+
+
test
+
+
+
test
+
+
+ +
+

test

+

test

+
+ + diff --git a/accessible/tests/mochitest/tree/test_display_contents.html b/accessible/tests/mochitest/tree/test_display_contents.html index 2cf60ce72aa0..8393a35b4179 100644 --- a/accessible/tests/mochitest/tree/test_display_contents.html +++ b/accessible/tests/mochitest/tree/test_display_contents.html @@ -36,10 +36,21 @@ function doTest() { ]}, ] }; testAccessibleTree("tableTableContents", tree); - testAccessibleTree("tableTbodyContents", tree); testAccessibleTree("tableTrContents", tree); testAccessibleTree("tableTdContents", tree); + tree = + { TABLE: [ + { GROUPING : [ + { ROW: [ + { CELL: [{ TEXT_LEAF: [] } ] }, + { CELL: [{ TEXT_LEAF: [] } ] }, + ]}, + ]}, + ] }; + testAccessibleTree("tableTbodyContents", tree); + + SimpleTest.finish(); } @@ -63,11 +74,6 @@ addA11yLoadEvent(doTest);
ab
- - - - -
ab
ab
@@ -77,5 +83,10 @@ addA11yLoadEvent(doTest); b + + + + +
ab