Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; 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 "XULListboxAccessible.h"
7 :
8 : #include "Accessible-inl.h"
9 : #include "nsAccessibilityService.h"
10 : #include "nsAccUtils.h"
11 : #include "DocAccessible.h"
12 : #include "Role.h"
13 : #include "States.h"
14 :
15 : #include "nsComponentManagerUtils.h"
16 : #include "nsIAutoCompleteInput.h"
17 : #include "nsIAutoCompletePopup.h"
18 : #include "nsIDOMXULMenuListElement.h"
19 : #include "nsIDOMXULMultSelectCntrlEl.h"
20 : #include "nsIDOMNodeList.h"
21 : #include "nsIDOMXULPopupElement.h"
22 : #include "nsIDOMXULSelectCntrlItemEl.h"
23 : #include "nsIMutableArray.h"
24 : #include "nsIPersistentProperties2.h"
25 :
26 : using namespace mozilla::a11y;
27 :
28 : ////////////////////////////////////////////////////////////////////////////////
29 : // XULColumAccessible
30 : ////////////////////////////////////////////////////////////////////////////////
31 :
32 0 : XULColumAccessible::
33 0 : XULColumAccessible(nsIContent* aContent, DocAccessible* aDoc) :
34 0 : AccessibleWrap(aContent, aDoc)
35 : {
36 0 : }
37 :
38 : role
39 0 : XULColumAccessible::NativeRole()
40 : {
41 0 : return roles::LIST;
42 : }
43 :
44 : uint64_t
45 0 : XULColumAccessible::NativeState()
46 : {
47 0 : return states::READONLY;
48 : }
49 :
50 :
51 : ////////////////////////////////////////////////////////////////////////////////
52 : // XULColumnItemAccessible
53 : ////////////////////////////////////////////////////////////////////////////////
54 :
55 0 : XULColumnItemAccessible::
56 0 : XULColumnItemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
57 0 : LeafAccessible(aContent, aDoc)
58 : {
59 0 : }
60 :
61 : role
62 0 : XULColumnItemAccessible::NativeRole()
63 : {
64 0 : return roles::COLUMNHEADER;
65 : }
66 :
67 : uint64_t
68 0 : XULColumnItemAccessible::NativeState()
69 : {
70 0 : return states::READONLY;
71 : }
72 :
73 : uint8_t
74 0 : XULColumnItemAccessible::ActionCount()
75 : {
76 0 : return 1;
77 : }
78 :
79 : void
80 0 : XULColumnItemAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
81 : {
82 0 : if (aIndex == eAction_Click)
83 0 : aName.AssignLiteral("click");
84 0 : }
85 :
86 : bool
87 0 : XULColumnItemAccessible::DoAction(uint8_t aIndex)
88 : {
89 0 : if (aIndex != eAction_Click)
90 0 : return false;
91 :
92 0 : DoCommand();
93 0 : return true;
94 : }
95 :
96 : ////////////////////////////////////////////////////////////////////////////////
97 : // XULListboxAccessible
98 : ////////////////////////////////////////////////////////////////////////////////
99 :
100 0 : XULListboxAccessible::
101 0 : XULListboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
102 0 : XULSelectControlAccessible(aContent, aDoc)
103 : {
104 0 : nsIContent* parentContent = mContent->GetFlattenedTreeParent();
105 0 : if (parentContent) {
106 : nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
107 0 : do_QueryInterface(parentContent);
108 0 : if (autoCompletePopupElm)
109 0 : mGenericTypes |= eAutoCompletePopup;
110 : }
111 :
112 0 : if (IsMulticolumn())
113 0 : mGenericTypes |= eTable;
114 0 : }
115 :
116 : ////////////////////////////////////////////////////////////////////////////////
117 : // XULListboxAccessible: Accessible
118 :
119 : uint64_t
120 0 : XULListboxAccessible::NativeState()
121 : {
122 : // As a XULListboxAccessible we can have the following states:
123 : // FOCUSED, READONLY, FOCUSABLE
124 :
125 : // Get focus status from base class
126 0 : uint64_t states = Accessible::NativeState();
127 :
128 : // see if we are multiple select if so set ourselves as such
129 :
130 0 : if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::seltype,
131 : nsGkAtoms::multiple, eCaseMatters)) {
132 0 : states |= states::MULTISELECTABLE | states::EXTSELECTABLE;
133 : }
134 :
135 0 : return states;
136 : }
137 :
138 : /**
139 : * Our value is the label of our ( first ) selected child.
140 : */
141 : void
142 0 : XULListboxAccessible::Value(nsString& aValue)
143 : {
144 0 : aValue.Truncate();
145 :
146 0 : nsCOMPtr<nsIDOMXULSelectControlElement> select(do_QueryInterface(mContent));
147 0 : if (select) {
148 0 : nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem;
149 0 : select->GetSelectedItem(getter_AddRefs(selectedItem));
150 0 : if (selectedItem)
151 0 : selectedItem->GetLabel(aValue);
152 : }
153 0 : }
154 :
155 : role
156 0 : XULListboxAccessible::NativeRole()
157 : {
158 : // A richlistbox is used with the new autocomplete URL bar, and has a parent
159 : // popup <panel>.
160 : nsCOMPtr<nsIDOMXULPopupElement> xulPopup =
161 0 : do_QueryInterface(mContent->GetParent());
162 0 : if (xulPopup)
163 0 : return roles::COMBOBOX_LIST;
164 :
165 0 : return IsMulticolumn() ? roles::TABLE : roles::LISTBOX;
166 : }
167 :
168 : ////////////////////////////////////////////////////////////////////////////////
169 : // XULListboxAccessible: Table
170 :
171 : uint32_t
172 0 : XULListboxAccessible::ColCount()
173 : {
174 0 : nsIContent* headContent = nullptr;
175 0 : for (nsIContent* childContent = mContent->GetFirstChild(); childContent;
176 0 : childContent = childContent->GetNextSibling()) {
177 0 : if (childContent->NodeInfo()->Equals(nsGkAtoms::listcols,
178 : kNameSpaceID_XUL)) {
179 0 : headContent = childContent;
180 : }
181 : }
182 0 : if (!headContent)
183 0 : return 0;
184 :
185 0 : uint32_t columnCount = 0;
186 0 : for (nsIContent* childContent = headContent->GetFirstChild(); childContent;
187 0 : childContent = childContent->GetNextSibling()) {
188 0 : if (childContent->NodeInfo()->Equals(nsGkAtoms::listcol,
189 : kNameSpaceID_XUL)) {
190 0 : columnCount++;
191 : }
192 : }
193 :
194 0 : return columnCount;
195 : }
196 :
197 : uint32_t
198 0 : XULListboxAccessible::RowCount()
199 : {
200 0 : nsCOMPtr<nsIDOMXULSelectControlElement> element(do_QueryInterface(mContent));
201 :
202 0 : uint32_t itemCount = 0;
203 0 : if(element)
204 0 : element->GetItemCount(&itemCount);
205 :
206 0 : return itemCount;
207 : }
208 :
209 : Accessible*
210 0 : XULListboxAccessible::CellAt(uint32_t aRowIndex, uint32_t aColumnIndex)
211 : {
212 : nsCOMPtr<nsIDOMXULSelectControlElement> control =
213 0 : do_QueryInterface(mContent);
214 0 : NS_ENSURE_TRUE(control, nullptr);
215 :
216 0 : nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
217 0 : control->GetItemAtIndex(aRowIndex, getter_AddRefs(item));
218 0 : if (!item)
219 0 : return nullptr;
220 :
221 0 : nsCOMPtr<nsIContent> itemContent(do_QueryInterface(item));
222 0 : if (!itemContent)
223 0 : return nullptr;
224 :
225 0 : Accessible* row = mDoc->GetAccessible(itemContent);
226 0 : NS_ENSURE_TRUE(row, nullptr);
227 :
228 0 : return row->GetChildAt(aColumnIndex);
229 : }
230 :
231 : bool
232 0 : XULListboxAccessible::IsColSelected(uint32_t aColIdx)
233 : {
234 : nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
235 0 : do_QueryInterface(mContent);
236 0 : NS_ASSERTION(control,
237 : "Doesn't implement nsIDOMXULMultiSelectControlElement.");
238 :
239 0 : int32_t selectedrowCount = 0;
240 0 : nsresult rv = control->GetSelectedCount(&selectedrowCount);
241 0 : NS_ENSURE_SUCCESS(rv, false);
242 :
243 0 : return selectedrowCount == static_cast<int32_t>(RowCount());
244 : }
245 :
246 : bool
247 0 : XULListboxAccessible::IsRowSelected(uint32_t aRowIdx)
248 : {
249 : nsCOMPtr<nsIDOMXULSelectControlElement> control =
250 0 : do_QueryInterface(mContent);
251 0 : NS_ASSERTION(control,
252 : "Doesn't implement nsIDOMXULSelectControlElement.");
253 :
254 0 : nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
255 0 : nsresult rv = control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
256 0 : NS_ENSURE_SUCCESS(rv, false);
257 :
258 0 : bool isSelected = false;
259 0 : item->GetSelected(&isSelected);
260 0 : return isSelected;
261 : }
262 :
263 : bool
264 0 : XULListboxAccessible::IsCellSelected(uint32_t aRowIdx, uint32_t aColIdx)
265 : {
266 0 : return IsRowSelected(aRowIdx);
267 : }
268 :
269 : uint32_t
270 0 : XULListboxAccessible::SelectedCellCount()
271 : {
272 : nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
273 0 : do_QueryInterface(mContent);
274 0 : NS_ASSERTION(control,
275 : "Doesn't implement nsIDOMXULMultiSelectControlElement.");
276 :
277 0 : nsCOMPtr<nsIDOMNodeList> selectedItems;
278 0 : control->GetSelectedItems(getter_AddRefs(selectedItems));
279 0 : if (!selectedItems)
280 0 : return 0;
281 :
282 0 : uint32_t selectedItemsCount = 0;
283 0 : nsresult rv = selectedItems->GetLength(&selectedItemsCount);
284 0 : NS_ENSURE_SUCCESS(rv, 0);
285 :
286 0 : return selectedItemsCount * ColCount();
287 : }
288 :
289 : uint32_t
290 0 : XULListboxAccessible::SelectedColCount()
291 : {
292 : nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
293 0 : do_QueryInterface(mContent);
294 0 : NS_ASSERTION(control,
295 : "Doesn't implement nsIDOMXULMultiSelectControlElement.");
296 :
297 0 : int32_t selectedRowCount = 0;
298 0 : nsresult rv = control->GetSelectedCount(&selectedRowCount);
299 0 : NS_ENSURE_SUCCESS(rv, 0);
300 :
301 0 : return selectedRowCount > 0 &&
302 0 : selectedRowCount == static_cast<int32_t>(RowCount()) ? ColCount() : 0;
303 : }
304 :
305 : uint32_t
306 0 : XULListboxAccessible::SelectedRowCount()
307 : {
308 : nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
309 0 : do_QueryInterface(mContent);
310 0 : NS_ASSERTION(control,
311 : "Doesn't implement nsIDOMXULMultiSelectControlElement.");
312 :
313 0 : int32_t selectedRowCount = 0;
314 0 : nsresult rv = control->GetSelectedCount(&selectedRowCount);
315 0 : NS_ENSURE_SUCCESS(rv, 0);
316 :
317 0 : return selectedRowCount >= 0 ? selectedRowCount : 0;
318 : }
319 :
320 : void
321 0 : XULListboxAccessible::SelectedCells(nsTArray<Accessible*>* aCells)
322 : {
323 : nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
324 0 : do_QueryInterface(mContent);
325 0 : NS_ASSERTION(control,
326 : "Doesn't implement nsIDOMXULMultiSelectControlElement.");
327 :
328 0 : nsCOMPtr<nsIDOMNodeList> selectedItems;
329 0 : control->GetSelectedItems(getter_AddRefs(selectedItems));
330 0 : if (!selectedItems)
331 0 : return;
332 :
333 0 : uint32_t selectedItemsCount = 0;
334 0 : DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
335 0 : NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
336 :
337 0 : for (uint32_t index = 0; index < selectedItemsCount; index++) {
338 0 : nsCOMPtr<nsIDOMNode> itemNode;
339 0 : selectedItems->Item(index, getter_AddRefs(itemNode));
340 0 : nsCOMPtr<nsIContent> itemContent(do_QueryInterface(itemNode));
341 0 : Accessible* item = mDoc->GetAccessible(itemContent);
342 :
343 0 : if (item) {
344 0 : uint32_t cellCount = item->ChildCount();
345 0 : for (uint32_t cellIdx = 0; cellIdx < cellCount; cellIdx++) {
346 0 : Accessible* cell = mChildren[cellIdx];
347 0 : if (cell->Role() == roles::CELL)
348 0 : aCells->AppendElement(cell);
349 : }
350 : }
351 : }
352 : }
353 :
354 : void
355 0 : XULListboxAccessible::SelectedCellIndices(nsTArray<uint32_t>* aCells)
356 : {
357 : nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
358 0 : do_QueryInterface(mContent);
359 0 : NS_ASSERTION(control,
360 : "Doesn't implement nsIDOMXULMultiSelectControlElement.");
361 :
362 0 : nsCOMPtr<nsIDOMNodeList> selectedItems;
363 0 : control->GetSelectedItems(getter_AddRefs(selectedItems));
364 0 : if (!selectedItems)
365 0 : return;
366 :
367 0 : uint32_t selectedItemsCount = 0;
368 0 : DebugOnly<nsresult> rv = selectedItems->GetLength(&selectedItemsCount);
369 0 : NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
370 :
371 0 : uint32_t colCount = ColCount();
372 0 : aCells->SetCapacity(selectedItemsCount * colCount);
373 0 : aCells->AppendElements(selectedItemsCount * colCount);
374 :
375 0 : for (uint32_t selItemsIdx = 0, cellsIdx = 0;
376 0 : selItemsIdx < selectedItemsCount; selItemsIdx++) {
377 :
378 0 : nsCOMPtr<nsIDOMNode> itemNode;
379 0 : selectedItems->Item(selItemsIdx, getter_AddRefs(itemNode));
380 : nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
381 0 : do_QueryInterface(itemNode);
382 :
383 0 : if (item) {
384 0 : int32_t itemIdx = -1;
385 0 : control->GetIndexOfItem(item, &itemIdx);
386 0 : if (itemIdx >= 0)
387 0 : for (uint32_t colIdx = 0; colIdx < colCount; colIdx++, cellsIdx++)
388 0 : aCells->ElementAt(cellsIdx) = itemIdx * colCount + colIdx;
389 : }
390 : }
391 : }
392 :
393 : void
394 0 : XULListboxAccessible::SelectedColIndices(nsTArray<uint32_t>* aCols)
395 : {
396 0 : uint32_t selColCount = SelectedColCount();
397 0 : aCols->SetCapacity(selColCount);
398 :
399 0 : for (uint32_t colIdx = 0; colIdx < selColCount; colIdx++)
400 0 : aCols->AppendElement(colIdx);
401 0 : }
402 :
403 : void
404 0 : XULListboxAccessible::SelectedRowIndices(nsTArray<uint32_t>* aRows)
405 : {
406 : nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
407 0 : do_QueryInterface(mContent);
408 0 : NS_ASSERTION(control,
409 : "Doesn't implement nsIDOMXULMultiSelectControlElement.");
410 :
411 0 : nsCOMPtr<nsIDOMNodeList> selectedItems;
412 0 : control->GetSelectedItems(getter_AddRefs(selectedItems));
413 0 : if (!selectedItems)
414 0 : return;
415 :
416 0 : uint32_t rowCount = 0;
417 0 : DebugOnly<nsresult> rv = selectedItems->GetLength(&rowCount);
418 0 : NS_ASSERTION(NS_SUCCEEDED(rv), "GetLength() Shouldn't fail!");
419 :
420 0 : if (!rowCount)
421 0 : return;
422 :
423 0 : aRows->SetCapacity(rowCount);
424 0 : aRows->AppendElements(rowCount);
425 :
426 0 : for (uint32_t rowIdx = 0; rowIdx < rowCount; rowIdx++) {
427 0 : nsCOMPtr<nsIDOMNode> itemNode;
428 0 : selectedItems->Item(rowIdx, getter_AddRefs(itemNode));
429 : nsCOMPtr<nsIDOMXULSelectControlItemElement> item =
430 0 : do_QueryInterface(itemNode);
431 :
432 0 : if (item) {
433 0 : int32_t itemIdx = -1;
434 0 : control->GetIndexOfItem(item, &itemIdx);
435 0 : if (itemIdx >= 0)
436 0 : aRows->ElementAt(rowIdx) = itemIdx;
437 : }
438 : }
439 : }
440 :
441 : void
442 0 : XULListboxAccessible::SelectRow(uint32_t aRowIdx)
443 : {
444 : nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
445 0 : do_QueryInterface(mContent);
446 0 : NS_ASSERTION(control,
447 : "Doesn't implement nsIDOMXULMultiSelectControlElement.");
448 :
449 0 : nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
450 0 : control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
451 0 : control->SelectItem(item);
452 0 : }
453 :
454 : void
455 0 : XULListboxAccessible::UnselectRow(uint32_t aRowIdx)
456 : {
457 : nsCOMPtr<nsIDOMXULMultiSelectControlElement> control =
458 0 : do_QueryInterface(mContent);
459 0 : NS_ASSERTION(control,
460 : "Doesn't implement nsIDOMXULMultiSelectControlElement.");
461 :
462 0 : nsCOMPtr<nsIDOMXULSelectControlItemElement> item;
463 0 : control->GetItemAtIndex(aRowIdx, getter_AddRefs(item));
464 0 : control->RemoveItemFromSelection(item);
465 0 : }
466 :
467 : ////////////////////////////////////////////////////////////////////////////////
468 : // XULListboxAccessible: Widgets
469 :
470 : bool
471 0 : XULListboxAccessible::IsWidget() const
472 : {
473 0 : return true;
474 : }
475 :
476 : bool
477 0 : XULListboxAccessible::IsActiveWidget() const
478 : {
479 0 : if (IsAutoCompletePopup()) {
480 : nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
481 0 : do_QueryInterface(mContent->GetParent());
482 :
483 0 : if (autoCompletePopupElm) {
484 0 : bool isOpen = false;
485 0 : autoCompletePopupElm->GetPopupOpen(&isOpen);
486 0 : return isOpen;
487 : }
488 : }
489 0 : return FocusMgr()->HasDOMFocus(mContent);
490 : }
491 :
492 : bool
493 0 : XULListboxAccessible::AreItemsOperable() const
494 : {
495 0 : if (IsAutoCompletePopup()) {
496 : nsCOMPtr<nsIAutoCompletePopup> autoCompletePopupElm =
497 0 : do_QueryInterface(mContent->GetParent());
498 :
499 0 : if (autoCompletePopupElm) {
500 0 : bool isOpen = false;
501 0 : autoCompletePopupElm->GetPopupOpen(&isOpen);
502 0 : return isOpen;
503 : }
504 : }
505 0 : return true;
506 : }
507 :
508 : Accessible*
509 0 : XULListboxAccessible::ContainerWidget() const
510 : {
511 0 : if (IsAutoCompletePopup()) {
512 : // This works for XUL autocompletes. It doesn't work for HTML forms
513 : // autocomplete because of potential crossprocess calls (when autocomplete
514 : // lives in content process while popup lives in chrome process). If that's
515 : // a problem then rethink Widgets interface.
516 : nsCOMPtr<nsIDOMXULMenuListElement> menuListElm =
517 0 : do_QueryInterface(mContent->GetParent());
518 0 : if (menuListElm) {
519 0 : nsCOMPtr<nsIDOMNode> inputElm;
520 0 : menuListElm->GetInputField(getter_AddRefs(inputElm));
521 0 : if (inputElm) {
522 0 : nsCOMPtr<nsINode> inputNode = do_QueryInterface(inputElm);
523 0 : if (inputNode) {
524 : Accessible* input =
525 0 : mDoc->GetAccessible(inputNode);
526 0 : return input ? input->ContainerWidget() : nullptr;
527 : }
528 : }
529 : }
530 : }
531 0 : return nullptr;
532 : }
533 :
534 : ////////////////////////////////////////////////////////////////////////////////
535 : // XULListitemAccessible
536 : ////////////////////////////////////////////////////////////////////////////////
537 :
538 0 : XULListitemAccessible::
539 0 : XULListitemAccessible(nsIContent* aContent, DocAccessible* aDoc) :
540 0 : XULMenuitemAccessible(aContent, aDoc)
541 : {
542 0 : mIsCheckbox = mContent->AttrValueIs(kNameSpaceID_None,
543 : nsGkAtoms::type,
544 : nsGkAtoms::checkbox,
545 : eCaseMatters);
546 0 : mType = eXULListItemType;
547 :
548 : // Walk XBL anonymous children for list items. Overrides the flag value from
549 : // base XULMenuitemAccessible class.
550 0 : mStateFlags &= ~eNoXBLKids;
551 0 : }
552 :
553 0 : XULListitemAccessible::~XULListitemAccessible()
554 : {
555 0 : }
556 :
557 0 : NS_IMPL_ISUPPORTS_INHERITED0(XULListitemAccessible, Accessible)
558 :
559 : Accessible*
560 0 : XULListitemAccessible::GetListAccessible() const
561 : {
562 0 : if (IsDefunct())
563 0 : return nullptr;
564 :
565 : nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
566 0 : do_QueryInterface(mContent);
567 0 : if (!listItem)
568 0 : return nullptr;
569 :
570 0 : nsCOMPtr<nsIDOMXULSelectControlElement> list;
571 0 : listItem->GetControl(getter_AddRefs(list));
572 :
573 0 : nsCOMPtr<nsIContent> listContent(do_QueryInterface(list));
574 0 : if (!listContent)
575 0 : return nullptr;
576 :
577 0 : return mDoc->GetAccessible(listContent);
578 : }
579 :
580 : ////////////////////////////////////////////////////////////////////////////////
581 : // XULListitemAccessible Accessible
582 :
583 : void
584 0 : XULListitemAccessible::Description(nsString& aDesc)
585 : {
586 0 : AccessibleWrap::Description(aDesc);
587 0 : }
588 :
589 : ////////////////////////////////////////////////////////////////////////////////
590 : // XULListitemAccessible: Accessible
591 :
592 : /**
593 : * If there is a Listcell as a child ( not anonymous ) use it, otherwise
594 : * default to getting the name from GetXULName
595 : */
596 : ENameValueFlag
597 0 : XULListitemAccessible::NativeName(nsString& aName)
598 : {
599 0 : nsIContent* childContent = mContent->GetFirstChild();
600 0 : if (childContent) {
601 0 : if (childContent->NodeInfo()->Equals(nsGkAtoms::listcell,
602 : kNameSpaceID_XUL)) {
603 0 : childContent->GetAttr(kNameSpaceID_None, nsGkAtoms::label, aName);
604 0 : return eNameOK;
605 : }
606 : }
607 :
608 0 : return Accessible::NativeName(aName);
609 : }
610 :
611 : role
612 0 : XULListitemAccessible::NativeRole()
613 : {
614 0 : Accessible* list = GetListAccessible();
615 0 : if (!list) {
616 0 : NS_ERROR("No list accessible for listitem accessible!");
617 0 : return roles::NOTHING;
618 : }
619 :
620 0 : if (list->Role() == roles::TABLE)
621 0 : return roles::ROW;
622 :
623 0 : if (mIsCheckbox)
624 0 : return roles::CHECK_RICH_OPTION;
625 :
626 0 : if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
627 0 : return roles::COMBOBOX_OPTION;
628 :
629 0 : return roles::RICH_OPTION;
630 : }
631 :
632 : uint64_t
633 0 : XULListitemAccessible::NativeState()
634 : {
635 0 : if (mIsCheckbox)
636 0 : return XULMenuitemAccessible::NativeState();
637 :
638 0 : uint64_t states = NativeInteractiveState();
639 :
640 : nsCOMPtr<nsIDOMXULSelectControlItemElement> listItem =
641 0 : do_QueryInterface(mContent);
642 :
643 0 : if (listItem) {
644 : bool isSelected;
645 0 : listItem->GetSelected(&isSelected);
646 0 : if (isSelected)
647 0 : states |= states::SELECTED;
648 :
649 0 : if (FocusMgr()->IsFocused(this))
650 0 : states |= states::FOCUSED;
651 : }
652 :
653 0 : return states;
654 : }
655 :
656 : uint64_t
657 0 : XULListitemAccessible::NativeInteractiveState() const
658 : {
659 0 : return NativelyUnavailable() || (mParent && mParent->NativelyUnavailable()) ?
660 0 : states::UNAVAILABLE : states::FOCUSABLE | states::SELECTABLE;
661 : }
662 :
663 : void
664 0 : XULListitemAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
665 : {
666 0 : if (aIndex == eAction_Click && mIsCheckbox) {
667 0 : uint64_t states = NativeState();
668 0 : if (states & states::CHECKED)
669 0 : aName.AssignLiteral("uncheck");
670 : else
671 0 : aName.AssignLiteral("check");
672 : }
673 0 : }
674 :
675 : ////////////////////////////////////////////////////////////////////////////////
676 : // XULListitemAccessible: Widgets
677 :
678 : Accessible*
679 0 : XULListitemAccessible::ContainerWidget() const
680 : {
681 0 : return Parent();
682 : }
683 :
684 :
685 : ////////////////////////////////////////////////////////////////////////////////
686 : // XULListCellAccessible
687 : ////////////////////////////////////////////////////////////////////////////////
688 :
689 0 : XULListCellAccessible::
690 0 : XULListCellAccessible(nsIContent* aContent, DocAccessible* aDoc) :
691 0 : HyperTextAccessibleWrap(aContent, aDoc)
692 : {
693 0 : mGenericTypes |= eTableCell;
694 0 : }
695 :
696 : ////////////////////////////////////////////////////////////////////////////////
697 : // nsISupports
698 :
699 0 : NS_IMPL_ISUPPORTS_INHERITED0(XULListCellAccessible,
700 : HyperTextAccessible)
701 :
702 : ////////////////////////////////////////////////////////////////////////////////
703 : // XULListCellAccessible: TableCell
704 :
705 : TableAccessible*
706 0 : XULListCellAccessible::Table() const
707 : {
708 0 : Accessible* thisRow = Parent();
709 0 : if (!thisRow || thisRow->Role() != roles::ROW)
710 0 : return nullptr;
711 :
712 0 : Accessible* table = thisRow->Parent();
713 0 : if (!table || table->Role() != roles::TABLE)
714 0 : return nullptr;
715 :
716 0 : return table->AsTable();
717 : }
718 :
719 : uint32_t
720 0 : XULListCellAccessible::ColIdx() const
721 : {
722 0 : Accessible* row = Parent();
723 0 : if (!row)
724 0 : return 0;
725 :
726 0 : int32_t indexInRow = IndexInParent();
727 0 : uint32_t colIdx = 0;
728 0 : for (int32_t idx = 0; idx < indexInRow; idx++) {
729 0 : Accessible* cell = row->GetChildAt(idx);
730 0 : roles::Role role = cell->Role();
731 0 : if (role == roles::CELL || role == roles::GRID_CELL ||
732 0 : role == roles::ROWHEADER || role == roles::COLUMNHEADER)
733 0 : colIdx++;
734 : }
735 :
736 0 : return colIdx;
737 : }
738 :
739 : uint32_t
740 0 : XULListCellAccessible::RowIdx() const
741 : {
742 0 : Accessible* row = Parent();
743 0 : if (!row)
744 0 : return 0;
745 :
746 0 : Accessible* table = row->Parent();
747 0 : if (!table)
748 0 : return 0;
749 :
750 0 : int32_t indexInTable = row->IndexInParent();
751 0 : uint32_t rowIdx = 0;
752 0 : for (int32_t idx = 0; idx < indexInTable; idx++) {
753 0 : row = table->GetChildAt(idx);
754 0 : if (row->Role() == roles::ROW)
755 0 : rowIdx++;
756 : }
757 :
758 0 : return rowIdx;
759 : }
760 :
761 : void
762 0 : XULListCellAccessible::ColHeaderCells(nsTArray<Accessible*>* aCells)
763 : {
764 0 : TableAccessible* table = Table();
765 0 : NS_ASSERTION(table, "cell not in a table!");
766 0 : if (!table)
767 0 : return;
768 :
769 : // Get column header cell from XUL listhead.
770 0 : Accessible* list = nullptr;
771 :
772 0 : Accessible* tableAcc = table->AsAccessible();
773 0 : uint32_t tableChildCount = tableAcc->ChildCount();
774 0 : for (uint32_t childIdx = 0; childIdx < tableChildCount; childIdx++) {
775 0 : Accessible* child = tableAcc->GetChildAt(childIdx);
776 0 : if (child->Role() == roles::LIST) {
777 0 : list = child;
778 0 : break;
779 : }
780 : }
781 :
782 0 : if (list) {
783 0 : Accessible* headerCell = list->GetChildAt(ColIdx());
784 0 : if (headerCell) {
785 0 : aCells->AppendElement(headerCell);
786 0 : return;
787 : }
788 : }
789 :
790 : // No column header cell from XUL markup, try to get it from ARIA markup.
791 0 : TableCellAccessible::ColHeaderCells(aCells);
792 : }
793 :
794 : bool
795 0 : XULListCellAccessible::Selected()
796 : {
797 0 : TableAccessible* table = Table();
798 0 : NS_ENSURE_TRUE(table, false); // we expect to be in a listbox (table)
799 :
800 0 : return table->IsRowSelected(RowIdx());
801 : }
802 :
803 : ////////////////////////////////////////////////////////////////////////////////
804 : // XULListCellAccessible. Accessible implementation
805 :
806 : role
807 0 : XULListCellAccessible::NativeRole()
808 : {
809 0 : return roles::CELL;
810 : }
811 :
812 : already_AddRefed<nsIPersistentProperties>
813 0 : XULListCellAccessible::NativeAttributes()
814 : {
815 : nsCOMPtr<nsIPersistentProperties> attributes =
816 0 : HyperTextAccessibleWrap::NativeAttributes();
817 :
818 : // "table-cell-index" attribute
819 0 : TableAccessible* table = Table();
820 0 : if (!table) // we expect to be in a listbox (table)
821 0 : return attributes.forget();
822 :
823 0 : nsAutoString stringIdx;
824 0 : stringIdx.AppendInt(table->CellIndexAt(RowIdx(), ColIdx()));
825 0 : nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);
826 :
827 0 : return attributes.forget();
828 : }
|