diff --git a/accessible/base/nsAccUtils.cpp b/accessible/base/nsAccUtils.cpp index aae2bc449f2..dc7d222bdcb 100644 --- a/accessible/base/nsAccUtils.cpp +++ b/accessible/base/nsAccUtils.cpp @@ -242,6 +242,27 @@ nsAccUtils::IsARIASelected(Accessible* aAccessible) nsGkAtoms::_true, eCaseMatters); } +Accessible* +nsAccUtils::TableFor(Accessible* aRow) +{ + if (aRow) { + Accessible* table = aRow->Parent(); + if (table) { + roles::Role tableRole = table->Role(); + if (tableRole == roles::GROUPING) { // if there's a rowgroup. + table = table->Parent(); + if (table) + tableRole = table->Role(); + } + + return tableRole == roles::TABLE || tableRole == roles::TREE_TABLE ? + table : nullptr; + } + } + + return nullptr; +} + HyperTextAccessible* nsAccUtils::GetTextContainer(nsINode* aNode) { diff --git a/accessible/base/nsAccUtils.h b/accessible/base/nsAccUtils.h index 9cd57c14063..57676b90a21 100644 --- a/accessible/base/nsAccUtils.h +++ b/accessible/base/nsAccUtils.h @@ -134,6 +134,8 @@ public: */ static HyperTextAccessible* GetTextContainer(nsINode* aNode); + static Accessible* TableFor(Accessible* aRow); + /** * Return true if the DOM node of given accessible has aria-selected="true" * attribute. diff --git a/accessible/base/nsAccessibilityService.cpp b/accessible/base/nsAccessibilityService.cpp index 547aef232c8..06fc7ac6e38 100644 --- a/accessible/base/nsAccessibilityService.cpp +++ b/accessible/base/nsAccessibilityService.cpp @@ -1092,11 +1092,12 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode, } if (!newAcc && content->IsHTMLElement()) { // HTML accessibles - bool isARIATableOrCell = roleMapEntry && - (roleMapEntry->accTypes & (eTableCell | eTable)); + bool isARIATablePart = roleMapEntry && + (roleMapEntry->accTypes & (eTableCell | eTableRow | eTable)); - if (!isARIATableOrCell || + if (!isARIATablePart || frame->AccessibleType() == eHTMLTableCellType || + frame->AccessibleType() == eHTMLTableRowType || frame->AccessibleType() == eHTMLTableType) { // Prefer to use markup to decide if and what kind of accessible to create, const MarkupMapInfo* markupMap = @@ -1108,13 +1109,17 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode, newAcc = CreateAccessibleByFrameType(frame, content, aContext); } - // In case of ARIA grids use grid-specific classes if it's not native table - // based. - if (isARIATableOrCell && (!newAcc || newAcc->IsGenericHyperText())) { + // 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 ARIAGridCellAccessibleWrap(content, document); + } else if (roleMapEntry->IsOfType(eTableRow)) { + if (aContext->IsTable()) + newAcc = new ARIARowAccessible(content, document); + } else if (roleMapEntry->IsOfType(eTable)) { newAcc = new ARIAGridAccessibleWrap(content, document); } diff --git a/accessible/base/nsCoreUtils.h b/accessible/base/nsCoreUtils.h index 85efe806364..c6e39688cdf 100644 --- a/accessible/base/nsCoreUtils.h +++ b/accessible/base/nsCoreUtils.h @@ -223,7 +223,7 @@ public: * attribute or wrong value then false is returned. */ static bool GetUIntAttr(nsIContent *aContent, nsIAtom *aAttr, - int32_t *aUInt); + int32_t* aUInt); /** * Returns language for the given node. diff --git a/accessible/generic/ARIAGridAccessible-inl.h b/accessible/generic/ARIAGridAccessible-inl.h index a502aa600e5..bb2bc9705b6 100644 --- a/accessible/generic/ARIAGridAccessible-inl.h +++ b/accessible/generic/ARIAGridAccessible-inl.h @@ -10,35 +10,15 @@ #include "ARIAGridAccessible.h" #include "AccIterator.h" +#include "nsAccUtils.h" namespace mozilla { namespace a11y { -inline Accessible* -ARIAGridCellAccessible::TableFor(Accessible* aRow) const -{ - if (aRow) { - Accessible* table = aRow->Parent(); - if (table) { - roles::Role tableRole = table->Role(); - if (tableRole == roles::GROUPING) { // if there's a rowgroup. - table = table->Parent(); - if (table) - tableRole = table->Role(); - } - - return tableRole == roles::TABLE || tableRole == roles::TREE_TABLE ? - table : nullptr; - } - } - - return nullptr; -} - inline int32_t ARIAGridCellAccessible::RowIndexFor(Accessible* aRow) const { - Accessible* table = TableFor(aRow); + Accessible* table = nsAccUtils::TableFor(aRow); if (table) { int32_t rowIdx = 0; Accessible* row = nullptr; diff --git a/accessible/generic/ARIAGridAccessible.cpp b/accessible/generic/ARIAGridAccessible.cpp index 37b49312dfa..39b62a5da8d 100644 --- a/accessible/generic/ARIAGridAccessible.cpp +++ b/accessible/generic/ARIAGridAccessible.cpp @@ -529,6 +529,34 @@ ARIAGridAccessible::SetARIASelected(Accessible* aAccessible, return NS_OK; } + +//////////////////////////////////////////////////////////////////////////////// +// ARIARowAccessible +//////////////////////////////////////////////////////////////////////////////// + +ARIARowAccessible:: + ARIARowAccessible(nsIContent* aContent, DocAccessible* aDoc) : + AccessibleWrap(aContent, aDoc) +{ + mGenericTypes |= eTableRow; +} + +NS_IMPL_ISUPPORTS_INHERITED0(ARIARowAccessible, Accessible) + +GroupPos +ARIARowAccessible::GroupPosition() +{ + int32_t count = 0, index = 0; + if (nsCoreUtils::GetUIntAttr(nsAccUtils::TableFor(this)->GetContent(), + nsGkAtoms::aria_rowcount, &count) && + nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_rowindex, &index)) { + return GroupPos(0, index, count); + } + + return AccessibleWrap::GroupPosition(); +} + + //////////////////////////////////////////////////////////////////////////////// // ARIAGridCellAccessible //////////////////////////////////////////////////////////////////////////////// @@ -552,7 +580,7 @@ NS_IMPL_ISUPPORTS_INHERITED0(ARIAGridCellAccessible, HyperTextAccessible) TableAccessible* ARIAGridCellAccessible::Table() const { - Accessible* table = TableFor(Row()); + Accessible* table = nsAccUtils::TableFor(Row()); return table ? table->AsTable() : nullptr; } @@ -657,3 +685,16 @@ ARIAGridCellAccessible::NativeAttributes() return attributes.forget(); } + +GroupPos +ARIAGridCellAccessible::GroupPosition() +{ + int32_t count = 0, index = 0; + if (nsCoreUtils::GetUIntAttr(Table()->AsAccessible()->GetContent(), + nsGkAtoms::aria_colcount, &count) && + nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_colindex, &index)) { + return GroupPos(0, index, count); + } + + return GroupPos(); +} diff --git a/accessible/generic/ARIAGridAccessible.h b/accessible/generic/ARIAGridAccessible.h index 7c56084898b..c9a36cc6ef1 100644 --- a/accessible/generic/ARIAGridAccessible.h +++ b/accessible/generic/ARIAGridAccessible.h @@ -73,6 +73,24 @@ protected: }; +/** + * Accessible for ARIA row. + */ +class ARIARowAccessible : public AccessibleWrap +{ +public: + ARIARowAccessible(nsIContent* aContent, DocAccessible* aDoc); + + NS_DECL_ISUPPORTS_INHERITED + + // Accessible + virtual mozilla::a11y::GroupPos GroupPosition() override; + +protected: + virtual ~ARIARowAccessible() {} +}; + + /** * Accessible for ARIA gridcell and rowheader/columnheader. */ @@ -88,6 +106,7 @@ public: virtual TableCellAccessible* AsTableCell() override { return this; } virtual void ApplyARIAState(uint64_t* aState) const override; virtual already_AddRefed NativeAttributes() override; + virtual mozilla::a11y::GroupPos GroupPosition() override; protected: virtual ~ARIAGridCellAccessible() {} @@ -98,14 +117,9 @@ protected: Accessible* Row() const { Accessible* row = Parent(); - return row && row->Role() == roles::ROW ? row : nullptr; + return row && row->IsTableRow() ? row : nullptr; } - /** - * Return a table for the given row. - */ - Accessible* TableFor(Accessible* aRow) const; - /** * Return index of the given row. */ diff --git a/accessible/generic/Accessible.h b/accessible/generic/Accessible.h index 03e9e7c03de..88050de28ef 100644 --- a/accessible/generic/Accessible.h +++ b/accessible/generic/Accessible.h @@ -82,6 +82,8 @@ enum ENameValueFlag { struct GroupPos { GroupPos() : level(0), posInSet(0), setSize(0) { } + GroupPos(int32_t aLevel, int32_t aPosInSet, int32_t aSetSize) : + level(aLevel), posInSet(aPosInSet), setSize(aSetSize) { } int32_t level; int32_t posInSet; diff --git a/accessible/html/HTMLTableAccessible.cpp b/accessible/html/HTMLTableAccessible.cpp index 4d44b76c7bf..3361ec80648 100644 --- a/accessible/html/HTMLTableAccessible.cpp +++ b/accessible/html/HTMLTableAccessible.cpp @@ -143,6 +143,19 @@ HTMLTableCellAccessible::NativeAttributes() return attributes.forget(); } +GroupPos +HTMLTableCellAccessible::GroupPosition() +{ + int32_t count = 0, index = 0; + if (nsCoreUtils::GetUIntAttr(Table()->AsAccessible()->GetContent(), + nsGkAtoms::aria_colcount, &count) && + nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_colindex, &index)) { + return GroupPos(0, index, count); + } + + return HyperTextAccessibleWrap::GroupPosition(); +} + //////////////////////////////////////////////////////////////////////////////// // HTMLTableCellAccessible: TableCellAccessible implementation @@ -356,6 +369,19 @@ HTMLTableRowAccessible::NativeRole() return roles::ROW; } +GroupPos +HTMLTableRowAccessible::GroupPosition() +{ + int32_t count = 0, index = 0; + if (nsCoreUtils::GetUIntAttr(nsAccUtils::TableFor(this)->GetContent(), + nsGkAtoms::aria_rowcount, &count) && + nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_rowindex, &index)) { + return GroupPos(0, index, count); + } + + return AccessibleWrap::GroupPosition(); +} + //////////////////////////////////////////////////////////////////////////////// // HTMLTableAccessible //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/html/HTMLTableAccessible.h b/accessible/html/HTMLTableAccessible.h index 47f6602cb79..5bef8e00d40 100644 --- a/accessible/html/HTMLTableAccessible.h +++ b/accessible/html/HTMLTableAccessible.h @@ -33,6 +33,7 @@ public: virtual uint64_t NativeState() override; virtual uint64_t NativeInteractiveState() const override; virtual already_AddRefed NativeAttributes() override; + virtual mozilla::a11y::GroupPos GroupPosition() override; // TableCellAccessible virtual TableAccessible* Table() const override; @@ -89,6 +90,7 @@ public: // Accessible virtual a11y::role NativeRole() override; + virtual mozilla::a11y::GroupPos GroupPosition() override; protected: virtual ~HTMLTableRowAccessible() { } diff --git a/accessible/tests/mochitest/attributes/test_obj_group.html b/accessible/tests/mochitest/attributes/test_obj_group.html index 64afbfcc7e8..28f45ad4b83 100644 --- a/accessible/tests/mochitest/attributes/test_obj_group.html +++ b/accessible/tests/mochitest/attributes/test_obj_group.html @@ -186,6 +186,11 @@ testGroupAttrs("combo1_opt3", 3, 4); testGroupAttrs("combo1_opt4", 4, 4); + ////////////////////////////////////////////////////////////////////////// + // ARIA table + testGroupAttrs("table_cell", 3, 4); + testGroupAttrs("table_row", 2, 2); + // Test that group position information updates after deleting node. testGroupAttrs("tree4_ti1", 1, 2, 1); testGroupAttrs("tree4_ti2", 2, 2, 1); @@ -442,5 +447,11 @@ + +
+
+
cell
+
+
diff --git a/dom/base/nsGkAtomList.h b/dom/base/nsGkAtomList.h index 008e588b76c..b190e1246b2 100644 --- a/dom/base/nsGkAtomList.h +++ b/dom/base/nsGkAtomList.h @@ -2241,6 +2241,8 @@ GK_ATOM(aria_atomic, "aria-atomic") GK_ATOM(aria_autocomplete, "aria-autocomplete") GK_ATOM(aria_busy, "aria-busy") GK_ATOM(aria_checked, "aria-checked") +GK_ATOM(aria_colcount, "aria-colcount") +GK_ATOM(aria_colindex, "aria-colindex") GK_ATOM(aria_controls, "aria-controls") GK_ATOM(aria_describedby, "aria-describedby") GK_ATOM(aria_disabled, "aria-disabled") @@ -2265,6 +2267,8 @@ GK_ATOM(aria_pressed, "aria-pressed") GK_ATOM(aria_readonly, "aria-readonly") GK_ATOM(aria_relevant, "aria-relevant") GK_ATOM(aria_required, "aria-required") +GK_ATOM(aria_rowcount, "aria-rowcount") +GK_ATOM(aria_rowindex, "aria-rowindex") GK_ATOM(aria_selected, "aria-selected") GK_ATOM(aria_setsize, "aria-setsize") GK_ATOM(aria_sort, "aria-sort")