Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/accessible/xul/XULTabAccessible.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 "XULTabAccessible.h"
7
8
#include "ARIAMap.h"
9
#include "nsAccUtils.h"
10
#include "Relation.h"
11
#include "Role.h"
12
#include "States.h"
13
14
// NOTE: alphabetically ordered
15
#include "nsIDocument.h"
16
#include "nsIDOMXULSelectCntrlEl.h"
17
#include "nsIDOMXULSelectCntrlItemEl.h"
18
#include "nsIDOMXULRelatedElement.h"
19
#include "nsXULElement.h"
20
21
#include "mozilla/dom/BindingDeclarations.h"
22
23
using namespace mozilla::a11y;
24
25
////////////////////////////////////////////////////////////////////////////////
26
// XULTabAccessible
27
////////////////////////////////////////////////////////////////////////////////
28
29
XULTabAccessible::
30
  XULTabAccessible(nsIContent* aContent, DocAccessible* aDoc) :
31
  HyperTextAccessibleWrap(aContent, aDoc)
32
0
{
33
0
}
34
35
////////////////////////////////////////////////////////////////////////////////
36
// XULTabAccessible: Accessible
37
38
uint8_t
39
XULTabAccessible::ActionCount() const
40
0
{
41
0
  return 1;
42
0
}
43
44
void
45
XULTabAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
46
0
{
47
0
  if (aIndex == eAction_Switch)
48
0
    aName.AssignLiteral("switch");
49
0
}
50
51
bool
52
XULTabAccessible::DoAction(uint8_t index) const
53
0
{
54
0
  if (index == eAction_Switch) {
55
0
    // XXXbz Could this just FromContent?
56
0
    RefPtr<nsXULElement> tab = nsXULElement::FromNodeOrNull(mContent);
57
0
    if (tab) {
58
0
      tab->Click(mozilla::dom::CallerType::System);
59
0
      return true;
60
0
    }
61
0
  }
62
0
  return false;
63
0
}
64
65
////////////////////////////////////////////////////////////////////////////////
66
// XULTabAccessible: Accessible
67
68
role
69
XULTabAccessible::NativeRole() const
70
0
{
71
0
  return roles::PAGETAB;
72
0
}
73
74
uint64_t
75
XULTabAccessible::NativeState() const
76
0
{
77
0
  // Possible states: focused, focusable, unavailable(disabled), offscreen.
78
0
79
0
  // get focus and disable status from base class
80
0
  uint64_t state = AccessibleWrap::NativeState();
81
0
82
0
  // Check whether the tab is selected and/or pinned
83
0
  nsCOMPtr<nsIDOMXULSelectControlItemElement> tab(do_QueryInterface(mContent));
84
0
  if (tab) {
85
0
    bool selected = false;
86
0
    if (NS_SUCCEEDED(tab->GetSelected(&selected)) && selected)
87
0
      state |= states::SELECTED;
88
0
89
0
    if (mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::pinned,
90
0
                                           nsGkAtoms::_true, eCaseMatters))
91
0
      state |= states::PINNED;
92
0
93
0
  }
94
0
95
0
  return state;
96
0
}
97
98
uint64_t
99
XULTabAccessible::NativeInteractiveState() const
100
0
{
101
0
  uint64_t state = Accessible::NativeInteractiveState();
102
0
  return (state & states::UNAVAILABLE) ? state : state | states::SELECTABLE;
103
0
}
104
105
Relation
106
XULTabAccessible::RelationByType(RelationType aType) const
107
0
{
108
0
  Relation rel = AccessibleWrap::RelationByType(aType);
109
0
  if (aType != RelationType::LABEL_FOR)
110
0
    return rel;
111
0
112
0
  // Expose 'LABEL_FOR' relation on tab accessible for tabpanel accessible.
113
0
  nsCOMPtr<nsIDOMXULRelatedElement> tabsElm =
114
0
    do_QueryInterface(mContent->GetParent());
115
0
  if (!tabsElm)
116
0
    return rel;
117
0
118
0
  RefPtr<mozilla::dom::Element> tabpanelElement;
119
0
  tabsElm->GetRelatedElement(GetNode(), getter_AddRefs(tabpanelElement));
120
0
  if (!tabpanelElement)
121
0
    return rel;
122
0
123
0
  rel.AppendTarget(mDoc, tabpanelElement);
124
0
  return rel;
125
0
}
126
127
void
128
XULTabAccessible::ApplyARIAState(uint64_t* aState) const
129
0
{
130
0
  HyperTextAccessibleWrap::ApplyARIAState(aState);
131
0
  // XUL tab has an implicit ARIA role of tab, so support aria-selected.
132
0
  // Don't use aria::MapToState because that will set the SELECTABLE state
133
0
  // even if the tab is disabled.
134
0
  if (nsAccUtils::IsARIASelected(this)) {
135
0
    *aState |= states::SELECTED;
136
0
  }
137
0
}
138
139
////////////////////////////////////////////////////////////////////////////////
140
// XULTabsAccessible
141
////////////////////////////////////////////////////////////////////////////////
142
143
XULTabsAccessible::
144
  XULTabsAccessible(nsIContent* aContent, DocAccessible* aDoc) :
145
  XULSelectControlAccessible(aContent, aDoc)
146
0
{
147
0
}
148
149
role
150
XULTabsAccessible::NativeRole() const
151
0
{
152
0
  return roles::PAGETABLIST;
153
0
}
154
155
uint8_t
156
XULTabsAccessible::ActionCount() const
157
0
{
158
0
  return 0;
159
0
}
160
161
void
162
XULTabsAccessible::Value(nsString& aValue) const
163
0
{
164
0
  aValue.Truncate();
165
0
}
166
167
ENameValueFlag
168
XULTabsAccessible::NativeName(nsString& aName) const
169
0
{
170
0
  // no name
171
0
  return eNameOK;
172
0
}
173
174
void
175
XULTabsAccessible::ApplyARIAState(uint64_t* aState) const
176
0
{
177
0
  XULSelectControlAccessible::ApplyARIAState(aState);
178
0
  // XUL tabs has an implicit ARIA role of tablist, so support
179
0
  // aria-multiselectable.
180
0
  MOZ_ASSERT(Elm());
181
0
  aria::MapToState(aria::eARIAMultiSelectable, Elm(), aState);
182
0
}
183
184
// XUL tabs is a single selection control and doesn't allow ARIA selection.
185
// However, if aria-multiselectable is used, it becomes a multiselectable
186
// control, where both native and ARIA markup are used to set selection.
187
// Therefore, if aria-multiselectable is set, use the base implementation of
188
// the selection retrieval methods in order to support ARIA selection.
189
// We don't bother overriding the selection setting methods because
190
// current front-end code using XUL tabs doesn't support setting of
191
//  aria-selected by the a11y engine and we still want to be able to set the
192
// primary selected item according to XUL.
193
194
void
195
XULTabsAccessible::SelectedItems(nsTArray<Accessible*>* aItems)
196
0
{
197
0
  if (nsAccUtils::IsARIAMultiSelectable(this)) {
198
0
    AccessibleWrap::SelectedItems(aItems);
199
0
  } else {
200
0
    XULSelectControlAccessible::SelectedItems(aItems);
201
0
  }
202
0
}
203
204
Accessible*
205
XULTabsAccessible::GetSelectedItem(uint32_t aIndex)
206
0
{
207
0
  if (nsAccUtils::IsARIAMultiSelectable(this)) {
208
0
    return AccessibleWrap::GetSelectedItem(aIndex);
209
0
  }
210
0
211
0
  return XULSelectControlAccessible::GetSelectedItem(aIndex);
212
0
}
213
214
uint32_t
215
XULTabsAccessible::SelectedItemCount()
216
0
{
217
0
  if (nsAccUtils::IsARIAMultiSelectable(this)) {
218
0
    return AccessibleWrap::SelectedItemCount();
219
0
  }
220
0
221
0
  return XULSelectControlAccessible::SelectedItemCount();
222
0
}
223
224
bool
225
XULTabsAccessible::IsItemSelected(uint32_t aIndex)
226
0
{
227
0
  if (nsAccUtils::IsARIAMultiSelectable(this)) {
228
0
    return AccessibleWrap::IsItemSelected(aIndex);
229
0
  }
230
0
231
0
  return XULSelectControlAccessible::IsItemSelected(aIndex);
232
0
}
233
234
235
////////////////////////////////////////////////////////////////////////////////
236
// XULTabpanelsAccessible
237
////////////////////////////////////////////////////////////////////////////////
238
239
role
240
XULTabpanelsAccessible::NativeRole() const
241
0
{
242
0
  return roles::PANE;
243
0
}
244
245
////////////////////////////////////////////////////////////////////////////////
246
// XULTabpanelAccessible
247
////////////////////////////////////////////////////////////////////////////////
248
249
XULTabpanelAccessible::
250
  XULTabpanelAccessible(nsIContent* aContent, DocAccessible* aDoc) :
251
  AccessibleWrap(aContent, aDoc)
252
0
{
253
0
}
254
255
role
256
XULTabpanelAccessible::NativeRole() const
257
0
{
258
0
  return roles::PROPERTYPAGE;
259
0
}
260
261
Relation
262
XULTabpanelAccessible::RelationByType(RelationType aType) const
263
0
{
264
0
  Relation rel = AccessibleWrap::RelationByType(aType);
265
0
  if (aType != RelationType::LABELLED_BY)
266
0
    return rel;
267
0
268
0
  // Expose 'LABELLED_BY' relation on tabpanel accessible for tab accessible.
269
0
  nsCOMPtr<nsIDOMXULRelatedElement> tabpanelsElm =
270
0
    do_QueryInterface(mContent->GetParent());
271
0
  if (!tabpanelsElm)
272
0
    return rel;
273
0
274
0
  RefPtr<mozilla::dom::Element> tabElement;
275
0
  tabpanelsElm->GetRelatedElement(GetNode(), getter_AddRefs(tabElement));
276
0
  if (!tabElement)
277
0
    return rel;
278
0
279
0
  rel.AppendTarget(mDoc, tabElement);
280
0
  return rel;
281
0
}