role HTMLTableHeaderCellAccessible::NativeRole() { // Check value of @scope attribute. static Element::AttrValuesArray scopeValues[] = { &nsGkAtoms::col, &nsGkAtoms::colgroup, &nsGkAtoms::row, &nsGkAtoms::rowgroup, nullptr }; int32_t valueIdx = mContent->AsElement()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::scope, scopeValues, eCaseMatters); switch (valueIdx) { case 0: case 1: return roles::COLUMNHEADER; case 2: case 3: return roles::ROWHEADER; } TableAccessible* table = Table(); if (!table) return roles::NOTHING; // If the cell next to this one is not a header cell then assume this cell is // a row header for it. uint32_t rowIdx = RowIdx(), colIdx = ColIdx(); Accessible* cell = table->CellAt(rowIdx, colIdx + ColExtent()); if (cell && !nsCoreUtils::IsHTMLTableHeader(cell->GetContent())) return roles::ROWHEADER; // If the cell below this one is not a header cell then assume this cell is // a column header for it. uint32_t rowExtent = RowExtent(); cell = table->CellAt(rowIdx + rowExtent, colIdx); if (cell && !nsCoreUtils::IsHTMLTableHeader(cell->GetContent())) return roles::COLUMNHEADER; // Otherwise if this cell is surrounded by header cells only then make a guess // based on its cell spanning. In other words if it is row spanned then assume // it's a row header, otherwise it's a column header. return rowExtent > 1 ? roles::ROWHEADER : roles::COLUMNHEADER; }