static AtkObject*
getRowHeaderCB(AtkTable *aTable, gint aRowIdx)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap)
    return nullptr;

  Accessible* cell = accWrap->AsTable()->CellAt(aRowIdx, 0);
  if (!cell)
    return nullptr;

  // If the cell at the first column is row header then assume it is row
  // header for all columns,
  if (cell->Role() == roles::ROWHEADER)
    return AccessibleWrap::GetAtkObject(cell);

  // otherwise get row header for the data cell at the first column.
  TableCellAccessible* tableCell = cell->AsTableCell();
  if (!tableCell)
    return nullptr;

  nsAutoTArray<Accessible*, 10> headerCells;
  tableCell->RowHeaderCells(&headerCells);
  if (headerCells.IsEmpty())
    return nullptr;

  return AccessibleWrap::GetAtkObject(headerCells[0]);
}
static gint
getColumnExtentAtCB(AtkTable *aTable, gint aRowIdx, gint aColIdx)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap || aRowIdx < 0 || aColIdx < 0)
    return -1;

    return static_cast<gint>(accWrap->AsTable()->ColExtentAt(aRowIdx, aColIdx));
}
static gint
getRowCountCB(AtkTable *aTable)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap)
    return -1;

    return static_cast<gint>(accWrap->AsTable()->RowCount());
}
static gint
getRowAtIndexCB(AtkTable *aTable, gint aIdx)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap || aIdx < 0)
    return -1;

    return static_cast<gint>(accWrap->AsTable()->RowIndexAt(aIdx));
}
static gboolean
isRowSelectedCB(AtkTable *aTable, gint aRowIdx)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap)
    return FALSE;

  return static_cast<gboolean>(accWrap->AsTable()->IsRowSelected(aRowIdx));
}
static AtkObject*
getCaptionCB(AtkTable* aTable)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap)
    return nullptr;

  Accessible* caption = accWrap->AsTable()->Caption();
  return caption ? AccessibleWrap::GetAtkObject(caption) : nullptr;
}
static const gchar*
getRowDescriptionCB(AtkTable *aTable, gint aRow)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap)
    return nullptr;

  nsAutoString autoStr;
  accWrap->AsTable()->RowDescription(aRow, autoStr);

  return AccessibleWrap::ReturnString(autoStr);
}
static gint
getIndexAtCB(AtkTable* aTable, gint aRow, gint aColumn)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap)
    return -1;

  TableAccessible* table = accWrap->AsTable();
  NS_ENSURE_TRUE(table, -1);

  return static_cast<gint>(table->CellIndexAt(aRow, aColumn));
}
static AtkObject*
getCaptionCB(AtkTable* aTable)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap)
    return nsnull;

  TableAccessible* table = accWrap->AsTable();
  NS_ENSURE_TRUE(table, nsnull);

  Accessible* caption = table->Caption();
  return caption ? AccessibleWrap::GetAtkObject(caption) : nsnull;
}
static AtkObject*
refAtCB(AtkTable* aTable, gint aRowIdx, gint aColIdx)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap || aRowIdx < 0 || aColIdx < 0)
    return nullptr;

  Accessible* cell = accWrap->AsTable()->CellAt(aRowIdx, aColIdx);
  if (!cell)
    return nullptr;

  AtkObject* cellAtkObj = AccessibleWrap::GetAtkObject(cell);
  if (cellAtkObj)
    g_object_ref(cellAtkObj);

  return cellAtkObj;
}
static gint
getSelectedRowsCB(AtkTable *aTable, gint **aSelected)
{
  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap)
    return 0;

  nsAutoTArray<uint32_t, 10> rows;
  accWrap->AsTable()->SelectedRowIndices(&rows);

  gint* atkRows = g_new(gint, rows.Length());
  if (!atkRows) {
    NS_WARNING("OUT OF MEMORY");
    return 0;
  }

  memcpy(atkRows, rows.Elements(), rows.Length() * sizeof(uint32_t));
  *aSelected = atkRows;
  return rows.Length();
}
static gint
getSelectedColumnsCB(AtkTable *aTable, gint** aSelected)
{
  *aSelected = nullptr;

  AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aTable));
  if (!accWrap)
    return 0;

  nsAutoTArray<uint32_t, 10> cols;
  accWrap->AsTable()->SelectedColIndices(&cols);
  if (cols.IsEmpty())
    return 0;

  gint* atkColumns = g_new(gint, cols.Length());
  if (!atkColumns) {
    NS_WARNING("OUT OF MEMORY");
    return 0;
  }

  memcpy(atkColumns, cols.Elements(), cols.Length() * sizeof(uint32_t));
  *aSelected = atkColumns;
  return cols.Length();
}