Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/accessible/generic/ARIAGridAccessible.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "ARIAGridAccessible-inl.h"
7
8
#include "Accessible-inl.h"
9
#include "AccIterator.h"
10
#include "nsAccUtils.h"
11
#include "Role.h"
12
#include "States.h"
13
14
#include "nsIMutableArray.h"
15
#include "nsIPersistentProperties2.h"
16
#include "nsComponentManagerUtils.h"
17
18
using namespace mozilla;
19
using namespace mozilla::a11y;
20
21
////////////////////////////////////////////////////////////////////////////////
22
// ARIAGridAccessible
23
////////////////////////////////////////////////////////////////////////////////
24
25
26
////////////////////////////////////////////////////////////////////////////////
27
// Constructor
28
29
ARIAGridAccessible::
30
  ARIAGridAccessible(nsIContent* aContent, DocAccessible* aDoc) :
31
  AccessibleWrap(aContent, aDoc)
32
0
{
33
0
  mGenericTypes |= eTable;
34
0
}
35
36
role
37
ARIAGridAccessible::NativeRole() const
38
0
{
39
0
  a11y::role r = GetAccService()->MarkupRole(mContent);
40
0
  return r != roles::NOTHING ? r : roles::TABLE;
41
0
}
42
43
already_AddRefed<nsIPersistentProperties>
44
ARIAGridAccessible::NativeAttributes()
45
0
{
46
0
  nsCOMPtr<nsIPersistentProperties> attributes =
47
0
    AccessibleWrap::NativeAttributes();
48
0
49
0
  if (IsProbablyLayoutTable()) {
50
0
    nsAutoString unused;
51
0
    attributes->SetStringProperty(NS_LITERAL_CSTRING("layout-guess"),
52
0
                                  NS_LITERAL_STRING("true"), unused);
53
0
  }
54
0
55
0
  return attributes.forget();
56
0
}
57
58
////////////////////////////////////////////////////////////////////////////////
59
// Table
60
61
uint32_t
62
ARIAGridAccessible::ColCount() const
63
0
{
64
0
  AccIterator rowIter(this, filters::GetRow);
65
0
  Accessible* row = rowIter.Next();
66
0
  if (!row)
67
0
    return 0;
68
0
69
0
  AccIterator cellIter(row, filters::GetCell);
70
0
  Accessible* cell = nullptr;
71
0
72
0
  uint32_t colCount = 0;
73
0
  while ((cell = cellIter.Next()))
74
0
    colCount++;
75
0
76
0
  return colCount;
77
0
}
78
79
uint32_t
80
ARIAGridAccessible::RowCount()
81
0
{
82
0
  uint32_t rowCount = 0;
83
0
  AccIterator rowIter(this, filters::GetRow);
84
0
  while (rowIter.Next())
85
0
    rowCount++;
86
0
87
0
  return rowCount;
88
0
}
89
90
Accessible*
91
ARIAGridAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex)
92
0
{
93
0
  Accessible* row = GetRowAt(aRowIndex);
94
0
  if (!row)
95
0
    return nullptr;
96
0
97
0
  return GetCellInRowAt(row, aColumnIndex);
98
0
}
99
100
bool
101
ARIAGridAccessible::IsColSelected(uint32_t aColIdx)
102
0
{
103
0
  if (IsARIARole(nsGkAtoms::table))
104
0
    return false;
105
0
106
0
  AccIterator rowIter(this, filters::GetRow);
107
0
  Accessible* row = rowIter.Next();
108
0
  if (!row)
109
0
    return false;
110
0
111
0
  do {
112
0
    if (!nsAccUtils::IsARIASelected(row)) {
113
0
      Accessible* cell = GetCellInRowAt(row, aColIdx);
114
0
      if (!cell || !nsAccUtils::IsARIASelected(cell))
115
0
        return false;
116
0
    }
117
0
  } while ((row = rowIter.Next()));
118
0
119
0
  return true;
120
0
}
121
122
bool
123
ARIAGridAccessible::IsRowSelected(uint32_t aRowIdx)
124
0
{
125
0
  if (IsARIARole(nsGkAtoms::table))
126
0
    return false;
127
0
128
0
  Accessible* row = GetRowAt(aRowIdx);
129
0
  if(!row)
130
0
    return false;
131
0
132
0
  if (!nsAccUtils::IsARIASelected(row)) {
133
0
    AccIterator cellIter(row, filters::GetCell);
134
0
    Accessible* cell = nullptr;
135
0
    while ((cell = cellIter.Next())) {
136
0
      if (!nsAccUtils::IsARIASelected(cell))
137
0
        return false;
138
0
    }
139
0
  }
140
0
141
0
  return true;
142
0
}
143
144
bool
145
ARIAGridAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx)
146
0
{
147
0
  if (IsARIARole(nsGkAtoms::table))
148
0
    return false;
149
0
150
0
  Accessible* row = GetRowAt(aRowIdx);
151
0
  if(!row)
152
0
    return false;
153
0
154
0
  if (!nsAccUtils::IsARIASelected(row)) {
155
0
    Accessible* cell = GetCellInRowAt(row, aColIdx);
156
0
    if (!cell || !nsAccUtils::IsARIASelected(cell))
157
0
      return false;
158
0
  }
159
0
160
0
  return true;
161
0
}
162
163
uint32_t
164
ARIAGridAccessible::SelectedCellCount()
165
0
{
166
0
  if (IsARIARole(nsGkAtoms::table))
167
0
    return 0;
168
0
169
0
  uint32_t count = 0, colCount = ColCount();
170
0
171
0
  AccIterator rowIter(this, filters::GetRow);
172
0
  Accessible* row = nullptr;
173
0
174
0
  while ((row = rowIter.Next())) {
175
0
    if (nsAccUtils::IsARIASelected(row)) {
176
0
      count += colCount;
177
0
      continue;
178
0
    }
179
0
180
0
    AccIterator cellIter(row, filters::GetCell);
181
0
    Accessible* cell = nullptr;
182
0
183
0
    while ((cell = cellIter.Next())) {
184
0
      if (nsAccUtils::IsARIASelected(cell))
185
0
        count++;
186
0
    }
187
0
  }
188
0
189
0
  return count;
190
0
}
191
192
uint32_t
193
ARIAGridAccessible::SelectedColCount()
194
0
{
195
0
  if (IsARIARole(nsGkAtoms::table))
196
0
    return 0;
197
0
198
0
  uint32_t colCount = ColCount();
199
0
  if (!colCount)
200
0
    return 0;
201
0
202
0
  AccIterator rowIter(this, filters::GetRow);
203
0
  Accessible* row = rowIter.Next();
204
0
  if (!row)
205
0
    return 0;
206
0
207
0
  nsTArray<bool> isColSelArray(colCount);
208
0
  isColSelArray.AppendElements(colCount);
209
0
  memset(isColSelArray.Elements(), true, colCount * sizeof(bool));
210
0
211
0
  uint32_t selColCount = colCount;
212
0
  do {
213
0
    if (nsAccUtils::IsARIASelected(row))
214
0
      continue;
215
0
216
0
    AccIterator cellIter(row, filters::GetCell);
217
0
    Accessible* cell = nullptr;
218
0
    for (uint32_t colIdx = 0;
219
0
         (cell = cellIter.Next()) && colIdx < colCount; colIdx++)
220
0
      if (isColSelArray[colIdx] && !nsAccUtils::IsARIASelected(cell)) {
221
0
        isColSelArray[colIdx] = false;
222
0
        selColCount--;
223
0
      }
224
0
  } while ((row = rowIter.Next()));
225
0
226
0
  return selColCount;
227
0
}
228
229
uint32_t
230
ARIAGridAccessible::SelectedRowCount()
231
0
{
232
0
  if (IsARIARole(nsGkAtoms::table))
233
0
    return 0;
234
0
235
0
  uint32_t count = 0;
236
0
237
0
  AccIterator rowIter(this, filters::GetRow);
238
0
  Accessible* row = nullptr;
239
0
240
0
  while ((row = rowIter.Next())) {
241
0
    if (nsAccUtils::IsARIASelected(row)) {
242
0
      count++;
243
0
      continue;
244
0
    }
245
0
246
0
    AccIterator cellIter(row, filters::GetCell);
247
0
    Accessible* cell = cellIter.Next();
248
0
    if (!cell)
249
0
      continue;
250
0
251
0
    bool isRowSelected = true;
252
0
    do {
253
0
      if (!nsAccUtils::IsARIASelected(cell)) {
254
0
        isRowSelected = false;
255
0
        break;
256
0
      }
257
0
    } while ((cell = cellIter.Next()));
258
0
259
0
    if (isRowSelected)
260
0
      count++;
261
0
  }
262
0
263
0
  return count;
264
0
}
265
266
void
267
ARIAGridAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
268
0
{
269
0
  if (IsARIARole(nsGkAtoms::table))
270
0
    return;
271
0
272
0
  AccIterator rowIter(this, filters::GetRow);
273
0
274
0
  Accessible* row = nullptr;
275
0
  while ((row = rowIter.Next())) {
276
0
    AccIterator cellIter(row, filters::GetCell);
277
0
    Accessible* cell = nullptr;
278
0
279
0
    if (nsAccUtils::IsARIASelected(row)) {
280
0
      while ((cell = cellIter.Next()))
281
0
        aCells->AppendElement(cell);
282
0
283
0
      continue;
284
0
    }
285
0
286
0
    while ((cell = cellIter.Next())) {
287
0
      if (nsAccUtils::IsARIASelected(cell))
288
0
        aCells->AppendElement(cell);
289
0
    }
290
0
  }
291
0
}
292
293
void
294
ARIAGridAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
295
0
{
296
0
  if (IsARIARole(nsGkAtoms::table))
297
0
    return;
298
0
299
0
  uint32_t colCount = ColCount();
300
0
301
0
  AccIterator rowIter(this, filters::GetRow);
302
0
  Accessible* row = nullptr;
303
0
  for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) {
304
0
    if (nsAccUtils::IsARIASelected(row)) {
305
0
      for (uint32_t colIdx = 0; colIdx < colCount; colIdx++)
306
0
        aCells->AppendElement(rowIdx * colCount + colIdx);
307
0
308
0
      continue;
309
0
    }
310
0
311
0
    AccIterator cellIter(row, filters::GetCell);
312
0
    Accessible* cell = nullptr;
313
0
    for (uint32_t colIdx = 0; (cell = cellIter.Next()); colIdx++) {
314
0
      if (nsAccUtils::IsARIASelected(cell))
315
0
        aCells->AppendElement(rowIdx * colCount + colIdx);
316
0
    }
317
0
  }
318
0
}
319
320
void
321
ARIAGridAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols)
322
0
{
323
0
  if (IsARIARole(nsGkAtoms::table))
324
0
    return;
325
0
326
0
  uint32_t colCount = ColCount();
327
0
  if (!colCount)
328
0
    return;
329
0
330
0
  AccIterator rowIter(this, filters::GetRow);
331
0
  Accessible* row = rowIter.Next();
332
0
  if (!row)
333
0
    return;
334
0
335
0
  nsTArray<bool> isColSelArray(colCount);
336
0
  isColSelArray.AppendElements(colCount);
337
0
  memset(isColSelArray.Elements(), true, colCount * sizeof(bool));
338
0
339
0
  do {
340
0
    if (nsAccUtils::IsARIASelected(row))
341
0
      continue;
342
0
343
0
    AccIterator cellIter(row, filters::GetCell);
344
0
    Accessible* cell = nullptr;
345
0
    for (uint32_t colIdx = 0;
346
0
         (cell = cellIter.Next()) && colIdx < colCount; colIdx++)
347
0
      if (isColSelArray[colIdx] && !nsAccUtils::IsARIASelected(cell)) {
348
0
        isColSelArray[colIdx] = false;
349
0
      }
350
0
  } while ((row = rowIter.Next()));
351
0
352
0
  for (uint32_t colIdx = 0; colIdx < colCount; colIdx++)
353
0
    if (isColSelArray[colIdx])
354
0
      aCols->AppendElement(colIdx);
355
0
}
356
357
void
358
ARIAGridAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows)
359
0
{
360
0
  if (IsARIARole(nsGkAtoms::table))
361
0
    return;
362
0
363
0
  AccIterator rowIter(this, filters::GetRow);
364
0
  Accessible* row = nullptr;
365
0
  for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) {
366
0
    if (nsAccUtils::IsARIASelected(row)) {
367
0
      aRows->AppendElement(rowIdx);
368
0
      continue;
369
0
    }
370
0
371
0
    AccIterator cellIter(row, filters::GetCell);
372
0
    Accessible* cell = cellIter.Next();
373
0
    if (!cell)
374
0
      continue;
375
0
376
0
    bool isRowSelected = true;
377
0
    do {
378
0
      if (!nsAccUtils::IsARIASelected(cell)) {
379
0
        isRowSelected = false;
380
0
        break;
381
0
      }
382
0
    } while ((cell = cellIter.Next()));
383
0
384
0
    if (isRowSelected)
385
0
      aRows->AppendElement(rowIdx);
386
0
  }
387
0
}
388
389
void
390
ARIAGridAccessible::SelectRow(uint32_t aRowIdx)
391
0
{
392
0
  if (IsARIARole(nsGkAtoms::table))
393
0
    return;
394
0
395
0
  AccIterator rowIter(this, filters::GetRow);
396
0
397
0
  Accessible* row = nullptr;
398
0
  for (uint32_t rowIdx = 0; (row = rowIter.Next()); rowIdx++) {
399
0
    DebugOnly<nsresult> rv = SetARIASelected(row, rowIdx == aRowIdx);
400
0
    NS_ASSERTION(NS_SUCCEEDED(rv), "SetARIASelected() Shouldn't fail!");
401
0
  }
402
0
}
403
404
void
405
ARIAGridAccessible::SelectCol(uint32_t aColIdx)
406
0
{
407
0
  if (IsARIARole(nsGkAtoms::table))
408
0
    return;
409
0
410
0
  AccIterator rowIter(this, filters::GetRow);
411
0
412
0
  Accessible* row = nullptr;
413
0
  while ((row = rowIter.Next())) {
414
0
    // Unselect all cells in the row.
415
0
    DebugOnly<nsresult> rv = SetARIASelected(row, false);
416
0
    NS_ASSERTION(NS_SUCCEEDED(rv), "SetARIASelected() Shouldn't fail!");
417
0
418
0
    // Select cell at the column index.
419
0
    Accessible* cell = GetCellInRowAt(row, aColIdx);
420
0
    if (cell)
421
0
      SetARIASelected(cell, true);
422
0
  }
423
0
}
424
425
void
426
ARIAGridAccessible::UnselectRow(uint32_t aRowIdx)
427
0
{
428
0
  if (IsARIARole(nsGkAtoms::table))
429
0
    return;
430
0
431
0
  Accessible* row = GetRowAt(aRowIdx);
432
0
  if (row)
433
0
    SetARIASelected(row, false);
434
0
}
435
436
void
437
ARIAGridAccessible::UnselectCol(uint32_t aColIdx)
438
0
{
439
0
  if (IsARIARole(nsGkAtoms::table))
440
0
    return;
441
0
442
0
  AccIterator rowIter(this, filters::GetRow);
443
0
444
0
  Accessible* row = nullptr;
445
0
  while ((row = rowIter.Next())) {
446
0
    Accessible* cell = GetCellInRowAt(row, aColIdx);
447
0
    if (cell)
448
0
      SetARIASelected(cell, false);
449
0
  }
450
0
}
451
452
////////////////////////////////////////////////////////////////////////////////
453
// Protected
454
455
Accessible*
456
ARIAGridAccessible::GetRowAt(int32_t aRow)
457
0
{
458
0
  int32_t rowIdx = aRow;
459
0
460
0
  AccIterator rowIter(this, filters::GetRow);
461
0
462
0
  Accessible* row = rowIter.Next();
463
0
  while (rowIdx != 0 && (row = rowIter.Next()))
464
0
    rowIdx--;
465
0
466
0
  return row;
467
0
}
468
469
Accessible*
470
ARIAGridAccessible::GetCellInRowAt(Accessible* aRow, int32_t aColumn)
471
0
{
472
0
  int32_t colIdx = aColumn;
473
0
474
0
  AccIterator cellIter(aRow, filters::GetCell);
475
0
  Accessible* cell = cellIter.Next();
476
0
  while (colIdx != 0 && (cell = cellIter.Next()))
477
0
    colIdx--;
478
0
479
0
  return cell;
480
0
}
481
482
nsresult
483
ARIAGridAccessible::SetARIASelected(Accessible* aAccessible,
484
                                    bool aIsSelected, bool aNotify)
485
0
{
486
0
  if (IsARIARole(nsGkAtoms::table))
487
0
    return NS_OK;
488
0
489
0
  nsIContent* content = aAccessible->GetContent();
490
0
  NS_ENSURE_STATE(content);
491
0
492
0
  nsresult rv = NS_OK;
493
0
  if (content->IsElement()) {
494
0
    if (aIsSelected)
495
0
      rv = content->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
496
0
                                         NS_LITERAL_STRING("true"), aNotify);
497
0
    else
498
0
      rv = content->AsElement()->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_selected,
499
0
                                         NS_LITERAL_STRING("false"), aNotify);
500
0
  }
501
0
502
0
  NS_ENSURE_SUCCESS(rv, rv);
503
0
504
0
  // No "smart" select/unselect for internal call.
505
0
  if (!aNotify)
506
0
    return NS_OK;
507
0
508
0
  // If row or cell accessible was selected then we're able to not bother about
509
0
  // selection of its cells or its row because our algorithm is row oriented,
510
0
  // i.e. we check selection on row firstly and then on cells.
511
0
  if (aIsSelected)
512
0
    return NS_OK;
513
0
514
0
  roles::Role role = aAccessible->Role();
515
0
516
0
  // If the given accessible is row that was unselected then remove
517
0
  // aria-selected from cell accessible.
518
0
  if (role == roles::ROW) {
519
0
    AccIterator cellIter(aAccessible, filters::GetCell);
520
0
    Accessible* cell = nullptr;
521
0
522
0
    while ((cell = cellIter.Next())) {
523
0
      rv = SetARIASelected(cell, false, false);
524
0
      NS_ENSURE_SUCCESS(rv, rv);
525
0
    }
526
0
    return NS_OK;
527
0
  }
528
0
529
0
  // If the given accessible is cell that was unselected and its row is selected
530
0
  // then remove aria-selected from row and put aria-selected on
531
0
  // siblings cells.
532
0
  if (role == roles::GRID_CELL || role == roles::ROWHEADER ||
533
0
      role == roles::COLUMNHEADER) {
534
0
    Accessible* row = aAccessible->Parent();
535
0
536
0
    if (row && row->Role() == roles::ROW &&
537
0
        nsAccUtils::IsARIASelected(row)) {
538
0
      rv = SetARIASelected(row, false, false);
539
0
      NS_ENSURE_SUCCESS(rv, rv);
540
0
541
0
      AccIterator cellIter(row, filters::GetCell);
542
0
      Accessible* cell = nullptr;
543
0
      while ((cell = cellIter.Next())) {
544
0
        if (cell != aAccessible) {
545
0
          rv = SetARIASelected(cell, true, false);
546
0
          NS_ENSURE_SUCCESS(rv, rv);
547
0
        }
548
0
      }
549
0
    }
550
0
  }
551
0
552
0
  return NS_OK;
553
0
}
554
555
556
////////////////////////////////////////////////////////////////////////////////
557
// ARIARowAccessible
558
////////////////////////////////////////////////////////////////////////////////
559
560
ARIARowAccessible::
561
  ARIARowAccessible(nsIContent* aContent, DocAccessible* aDoc) :
562
  AccessibleWrap(aContent, aDoc)
563
0
{
564
0
  mGenericTypes |= eTableRow;
565
0
}
566
567
role
568
ARIARowAccessible::NativeRole() const
569
0
{
570
0
  a11y::role r = GetAccService()->MarkupRole(mContent);
571
0
  return r != roles::NOTHING ? r : roles::ROW;
572
0
}
573
574
GroupPos
575
ARIARowAccessible::GroupPosition()
576
0
{
577
0
  int32_t count = 0, index = 0;
578
0
  Accessible* table = nsAccUtils::TableFor(this);
579
0
  if (table && nsCoreUtils::GetUIntAttr(table->GetContent(),
580
0
                                        nsGkAtoms::aria_rowcount, &count) &&
581
0
      nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_rowindex, &index)) {
582
0
    return GroupPos(0, index, count);
583
0
  }
584
0
585
0
  return AccessibleWrap::GroupPosition();
586
0
}
587
588
589
////////////////////////////////////////////////////////////////////////////////
590
// ARIAGridCellAccessible
591
////////////////////////////////////////////////////////////////////////////////
592
593
594
////////////////////////////////////////////////////////////////////////////////
595
// Constructor
596
597
ARIAGridCellAccessible::
598
  ARIAGridCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
599
  HyperTextAccessibleWrap(aContent, aDoc)
600
0
{
601
0
  mGenericTypes |= eTableCell;
602
0
}
603
604
role
605
ARIAGridCellAccessible::NativeRole() const
606
0
{
607
0
  a11y::role r = GetAccService()->MarkupRole(mContent);
608
0
  return r != roles::NOTHING ? r : roles::CELL;
609
0
}
610
611
////////////////////////////////////////////////////////////////////////////////
612
// TableCell
613
614
TableAccessible*
615
ARIAGridCellAccessible::Table() const
616
0
{
617
0
  Accessible* table = nsAccUtils::TableFor(Row());
618
0
  return table ? table->AsTable() : nullptr;
619
0
}
620
621
uint32_t
622
ARIAGridCellAccessible::ColIdx() const
623
0
{
624
0
  Accessible* row = Row();
625
0
  if (!row)
626
0
    return 0;
627
0
628
0
  int32_t indexInRow = IndexInParent();
629
0
  uint32_t colIdx = 0;
630
0
  for (int32_t idx = 0; idx < indexInRow; idx++) {
631
0
    Accessible* cell = row->GetChildAt(idx);
632
0
    roles::Role role = cell->Role();
633
0
    if (role == roles::CELL || role == roles::GRID_CELL ||
634
0
        role == roles::ROWHEADER || role == roles::COLUMNHEADER)
635
0
      colIdx++;
636
0
  }
637
0
638
0
  return colIdx;
639
0
}
640
641
uint32_t
642
ARIAGridCellAccessible::RowIdx() const
643
0
{
644
0
  return RowIndexFor(Row());
645
0
}
646
647
bool
648
ARIAGridCellAccessible::Selected()
649
0
{
650
0
  Accessible* row = Row();
651
0
  if (!row)
652
0
    return false;
653
0
654
0
  return nsAccUtils::IsARIASelected(row) || nsAccUtils::IsARIASelected(this);
655
0
}
656
657
////////////////////////////////////////////////////////////////////////////////
658
// Accessible
659
660
void
661
ARIAGridCellAccessible::ApplyARIAState(uint64_t* aState) const
662
0
{
663
0
  HyperTextAccessibleWrap::ApplyARIAState(aState);
664
0
665
0
  // Return if the gridcell has aria-selected="true".
666
0
  if (*aState & states::SELECTED)
667
0
    return;
668
0
669
0
  // Check aria-selected="true" on the row.
670
0
  Accessible* row = Parent();
671
0
  if (!row || row->Role() != roles::ROW)
672
0
    return;
673
0
674
0
  nsIContent *rowContent = row->GetContent();
675
0
  if (nsAccUtils::HasDefinedARIAToken(rowContent, nsGkAtoms::aria_selected) &&
676
0
      !rowContent->AsElement()->AttrValueIs(kNameSpaceID_None,
677
0
                                            nsGkAtoms::aria_selected,
678
0
                                            nsGkAtoms::_false, eCaseMatters))
679
0
    *aState |= states::SELECTABLE | states::SELECTED;
680
0
}
681
682
already_AddRefed<nsIPersistentProperties>
683
ARIAGridCellAccessible::NativeAttributes()
684
0
{
685
0
  nsCOMPtr<nsIPersistentProperties> attributes =
686
0
    HyperTextAccessibleWrap::NativeAttributes();
687
0
688
0
  // Expose "table-cell-index" attribute.
689
0
  Accessible* thisRow = Row();
690
0
  if (!thisRow)
691
0
    return attributes.forget();
692
0
693
0
  int32_t colIdx = 0, colCount = 0;
694
0
  uint32_t childCount = thisRow->ChildCount();
695
0
  for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
696
0
    Accessible* child = thisRow->GetChildAt(childIdx);
697
0
    if (child == this)
698
0
      colIdx = colCount;
699
0
700
0
    roles::Role role = child->Role();
701
0
    if (role == roles::CELL || role == roles::GRID_CELL ||
702
0
        role == roles::ROWHEADER || role == roles::COLUMNHEADER)
703
0
      colCount++;
704
0
  }
705
0
706
0
  int32_t rowIdx = RowIndexFor(thisRow);
707
0
708
0
  nsAutoString stringIdx;
709
0
  stringIdx.AppendInt(rowIdx * colCount + colIdx);
710
0
  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
711
0
712
#ifdef DEBUG
713
  nsAutoString unused;
714
  attributes->SetStringProperty(NS_LITERAL_CSTRING("cppclass"),
715
                                NS_LITERAL_STRING("ARIAGridCellAccessible"),
716
                                unused);
717
#endif
718
719
0
  return attributes.forget();
720
0
}
721
722
GroupPos
723
ARIAGridCellAccessible::GroupPosition()
724
0
{
725
0
  int32_t count = 0, index = 0;
726
0
  TableAccessible* table = Table();
727
0
  if (table && nsCoreUtils::GetUIntAttr(table->AsAccessible()->GetContent(),
728
0
                                        nsGkAtoms::aria_colcount, &count) &&
729
0
      nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_colindex, &index)) {
730
0
    return GroupPos(0, index, count);
731
0
  }
732
0
733
0
  return GroupPos();
734
0
}