Bug 1177268 - implement aria-rowcount/index and aria-colcount/index, r=marcoz

This commit is contained in:
Alexander Surkov 2015-06-26 14:41:22 -07:00
parent b84d91ee7e
commit b3627cf530
12 changed files with 144 additions and 36 deletions

View File

@ -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)
{

View File

@ -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.

View File

@ -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);
}

View File

@ -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.

View File

@ -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;

View File

@ -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();
}

View File

@ -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<nsIPersistentProperties> 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.
*/

View File

@ -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;

View File

@ -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
////////////////////////////////////////////////////////////////////////////////

View File

@ -33,6 +33,7 @@ public:
virtual uint64_t NativeState() override;
virtual uint64_t NativeInteractiveState() const override;
virtual already_AddRefed<nsIPersistentProperties> 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() { }

View File

@ -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 @@
<input type="radio" style="display: none;" name="group3">
<input type="radio" id="radio5" name="group3">
</form>
<div role="table" aria-colcount="4" aria-rowcount="2">
<div role="row" id="table_row" aria-rowindex="2">
<div role="cell" id="table_cell" aria-colindex="3">cell</div>
</div>
</div>
</body>
</html>

View File

@ -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")