Bug 1793748: Don't treat a role="row" as a table row if it has an invalid parent. r=morgan

Previously, we were inconsistent in what we treated as a table row in various places.
This caused breakage after bug 1726124, since nsAccUtils::TableFor() started returning a table when an ARIA row had an invalid parent, but Filters::GetRow wouldn't find such a row
This was causing broken expectations (and consequently, an extremely long loop) in TableCellAccessible::PrevColHeader.
To fix this, avoid creating an ARIARowAccessible (and thus ARIAGridCellAccessibles) if the row's parent isn't valid.
This way, there aren't conflicting expectations because the TableCellAccessible code can never run.
Furthermore, clients don't get a broken table cell interface on invalid cells, which was a problem even before bug 1726124.

Differential Revision: https://phabricator.services.mozilla.com/D159679
This commit is contained in:
James Teh 2022-10-19 21:50:22 +00:00
Родитель fd4b32e3e9
Коммит ff93da3728
3 изменённых файлов: 46 добавлений и 4 удалений

Просмотреть файл

@ -1049,7 +1049,13 @@ LocalAccessible* nsAccessibilityService::CreateAccessible(
} else if (roleMapEntry->IsOfType(eTableRow)) {
if (aContext->IsTable() ||
(aContext->LocalParent() && aContext->LocalParent()->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);
}

Просмотреть файл

@ -447,17 +447,17 @@ class Accessible {
bool IsDoc() const { return HasGenericType(eDocument); }
bool IsTableRow() const { return HasGenericType(eTableRow); }
/**
* Note: The eTable* types defined in the ARIA map are used in
* nsAccessibilityService::CreateAccessible to determine which ARIAGrid*
* classes to use for accessible object creation. However, an invalid table
* structure might cause these classes not to be used after all.
*
* To make sure we're really dealing with a table/cell, only check the
* To make sure we're really dealing with a table/row/cell, only check the
* generic type defined by the class, not the type defined in the ARIA map.
*/
bool IsTableRow() const { return mGenericTypes & eTableRow; }
bool IsTableCell() const { return mGenericTypes & eTableCell; }
bool IsTable() const { return mGenericTypes & eTable; }

Просмотреть файл

@ -432,6 +432,7 @@ addAccessibleTask(
let queryOk = false;
try {
table.QueryInterface(nsIAccessibleTable);
queryOk = true;
} catch (e) {}
todo(queryOk, "Got nsIAccessibleTable");
},
@ -442,3 +443,38 @@ addAccessibleTask(
remoteIframe: isCacheEnabled,
}
);
/**
* Test a broken ARIA table with an invalid cell.
*/
addAccessibleTask(
`
<div id="table" role="table">
<div role="main">
<div role="row">
<div id="cell" role="cell">a</div>
</div>
</div>
</div>
`,
async function(browser, docAcc) {
const table = findAccessibleChildByID(docAcc, "table", [
nsIAccessibleTable,
]);
is(table.rowCount, 0, "table rowCount correct");
is(table.columnCount, 0, "table columnCount correct");
const cell = findAccessibleChildByID(docAcc, "cell");
let queryOk = false;
try {
cell.QueryInterface(nsIAccessibleTableCell);
queryOk = true;
} catch (e) {}
ok(!queryOk, "Got nsIAccessibleTableCell on an invalid cell");
},
{
chrome: true,
topLevel: isCacheEnabled,
iframe: isCacheEnabled,
remoteIframe: isCacheEnabled,
}
);