|
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 "XULElementAccessibles.h" |
|
7 |
|
8 #include "Accessible-inl.h" |
|
9 #include "BaseAccessibles.h" |
|
10 #include "DocAccessible-inl.h" |
|
11 #include "nsAccUtils.h" |
|
12 #include "nsCoreUtils.h" |
|
13 #include "nsTextEquivUtils.h" |
|
14 #include "Relation.h" |
|
15 #include "Role.h" |
|
16 #include "States.h" |
|
17 #include "TextUpdater.h" |
|
18 |
|
19 #ifdef A11Y_LOG |
|
20 #include "Logging.h" |
|
21 #endif |
|
22 |
|
23 #include "nsIAccessibleRelation.h" |
|
24 #include "nsIDOMXULDescriptionElement.h" |
|
25 #include "nsNameSpaceManager.h" |
|
26 #include "nsNetUtil.h" |
|
27 #include "nsString.h" |
|
28 #include "nsTextBoxFrame.h" |
|
29 |
|
30 using namespace mozilla::a11y; |
|
31 |
|
32 //////////////////////////////////////////////////////////////////////////////// |
|
33 // XULLabelAccessible |
|
34 //////////////////////////////////////////////////////////////////////////////// |
|
35 |
|
36 XULLabelAccessible:: |
|
37 XULLabelAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
38 HyperTextAccessibleWrap(aContent, aDoc) |
|
39 { |
|
40 mType = eXULLabelType; |
|
41 |
|
42 // If @value attribute is given then it's rendered instead text content. In |
|
43 // this case we need to create a text leaf accessible to make @value attribute |
|
44 // accessible. |
|
45 // XXX: text interface doesn't let you get the text by words. |
|
46 nsTextBoxFrame* textBoxFrame = do_QueryFrame(mContent->GetPrimaryFrame()); |
|
47 if (textBoxFrame) { |
|
48 mValueTextLeaf = new XULLabelTextLeafAccessible(mContent, mDoc); |
|
49 mDoc->BindToDocument(mValueTextLeaf, nullptr); |
|
50 |
|
51 nsAutoString text; |
|
52 textBoxFrame->GetCroppedTitle(text); |
|
53 mValueTextLeaf->SetText(text); |
|
54 } |
|
55 } |
|
56 |
|
57 void |
|
58 XULLabelAccessible::Shutdown() |
|
59 { |
|
60 mValueTextLeaf = nullptr; |
|
61 HyperTextAccessibleWrap::Shutdown(); |
|
62 } |
|
63 |
|
64 ENameValueFlag |
|
65 XULLabelAccessible::NativeName(nsString& aName) |
|
66 { |
|
67 // if the value attr doesn't exist, the screen reader must get the accessible text |
|
68 // from the accessible text interface or from the children |
|
69 if (mValueTextLeaf) |
|
70 return mValueTextLeaf->Name(aName); |
|
71 |
|
72 return eNameOK; |
|
73 } |
|
74 |
|
75 role |
|
76 XULLabelAccessible::NativeRole() |
|
77 { |
|
78 return roles::LABEL; |
|
79 } |
|
80 |
|
81 uint64_t |
|
82 XULLabelAccessible::NativeState() |
|
83 { |
|
84 // Labels and description have read only state |
|
85 // They are not focusable or selectable |
|
86 return HyperTextAccessibleWrap::NativeState() | states::READONLY; |
|
87 } |
|
88 |
|
89 Relation |
|
90 XULLabelAccessible::RelationByType(RelationType aType) |
|
91 { |
|
92 Relation rel = HyperTextAccessibleWrap::RelationByType(aType); |
|
93 if (aType == RelationType::LABEL_FOR) { |
|
94 // Caption is the label for groupbox |
|
95 nsIContent* parent = mContent->GetFlattenedTreeParent(); |
|
96 if (parent && parent->Tag() == nsGkAtoms::caption) { |
|
97 Accessible* parent = Parent(); |
|
98 if (parent && parent->Role() == roles::GROUPING) |
|
99 rel.AppendTarget(parent); |
|
100 } |
|
101 } |
|
102 |
|
103 return rel; |
|
104 } |
|
105 |
|
106 void |
|
107 XULLabelAccessible::UpdateLabelValue(const nsString& aValue) |
|
108 { |
|
109 #ifdef A11Y_LOG |
|
110 if (logging::IsEnabled(logging::eText)) { |
|
111 logging::MsgBegin("TEXT", "text may be changed (xul:label @value update)"); |
|
112 logging::Node("container", mContent); |
|
113 logging::MsgEntry("old text '%s'", |
|
114 NS_ConvertUTF16toUTF8(mValueTextLeaf->Text()).get()); |
|
115 logging::MsgEntry("new text: '%s'", |
|
116 NS_ConvertUTF16toUTF8(aValue).get()); |
|
117 logging::MsgEnd(); |
|
118 } |
|
119 #endif |
|
120 |
|
121 TextUpdater::Run(mDoc, mValueTextLeaf, aValue); |
|
122 } |
|
123 |
|
124 void |
|
125 XULLabelAccessible::CacheChildren() |
|
126 { |
|
127 if (mValueTextLeaf) { |
|
128 AppendChild(mValueTextLeaf); |
|
129 return; |
|
130 } |
|
131 |
|
132 // Cache children from subtree. |
|
133 AccessibleWrap::CacheChildren(); |
|
134 } |
|
135 |
|
136 |
|
137 //////////////////////////////////////////////////////////////////////////////// |
|
138 // XULLabelTextLeafAccessible |
|
139 //////////////////////////////////////////////////////////////////////////////// |
|
140 |
|
141 role |
|
142 XULLabelTextLeafAccessible::NativeRole() |
|
143 { |
|
144 return roles::TEXT_LEAF; |
|
145 } |
|
146 |
|
147 uint64_t |
|
148 XULLabelTextLeafAccessible::NativeState() |
|
149 { |
|
150 return TextLeafAccessibleWrap::NativeState() | states::READONLY; |
|
151 } |
|
152 |
|
153 |
|
154 //////////////////////////////////////////////////////////////////////////////// |
|
155 // XULTooltipAccessible |
|
156 //////////////////////////////////////////////////////////////////////////////// |
|
157 |
|
158 XULTooltipAccessible:: |
|
159 XULTooltipAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
160 LeafAccessible(aContent, aDoc) |
|
161 { |
|
162 } |
|
163 |
|
164 uint64_t |
|
165 XULTooltipAccessible::NativeState() |
|
166 { |
|
167 return LeafAccessible::NativeState() | states::READONLY; |
|
168 } |
|
169 |
|
170 role |
|
171 XULTooltipAccessible::NativeRole() |
|
172 { |
|
173 return roles::TOOLTIP; |
|
174 } |
|
175 |
|
176 |
|
177 //////////////////////////////////////////////////////////////////////////////// |
|
178 // XULLinkAccessible |
|
179 //////////////////////////////////////////////////////////////////////////////// |
|
180 |
|
181 XULLinkAccessible:: |
|
182 XULLinkAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
183 XULLabelAccessible(aContent, aDoc) |
|
184 { |
|
185 } |
|
186 |
|
187 // Expose nsIAccessibleHyperLink unconditionally |
|
188 NS_IMPL_ISUPPORTS_INHERITED(XULLinkAccessible, XULLabelAccessible, |
|
189 nsIAccessibleHyperLink) |
|
190 |
|
191 //////////////////////////////////////////////////////////////////////////////// |
|
192 // XULLinkAccessible. nsIAccessible |
|
193 |
|
194 void |
|
195 XULLinkAccessible::Value(nsString& aValue) |
|
196 { |
|
197 aValue.Truncate(); |
|
198 |
|
199 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, aValue); |
|
200 } |
|
201 |
|
202 ENameValueFlag |
|
203 XULLinkAccessible::NativeName(nsString& aName) |
|
204 { |
|
205 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName); |
|
206 if (!aName.IsEmpty()) |
|
207 return eNameOK; |
|
208 |
|
209 nsTextEquivUtils::GetNameFromSubtree(this, aName); |
|
210 return aName.IsEmpty() ? eNameOK : eNameFromSubtree; |
|
211 } |
|
212 |
|
213 role |
|
214 XULLinkAccessible::NativeRole() |
|
215 { |
|
216 return roles::LINK; |
|
217 } |
|
218 |
|
219 |
|
220 uint64_t |
|
221 XULLinkAccessible::NativeLinkState() const |
|
222 { |
|
223 return states::LINKED; |
|
224 } |
|
225 |
|
226 uint8_t |
|
227 XULLinkAccessible::ActionCount() |
|
228 { |
|
229 return 1; |
|
230 } |
|
231 |
|
232 NS_IMETHODIMP |
|
233 XULLinkAccessible::GetActionName(uint8_t aIndex, nsAString& aName) |
|
234 { |
|
235 aName.Truncate(); |
|
236 |
|
237 if (aIndex != eAction_Jump) |
|
238 return NS_ERROR_INVALID_ARG; |
|
239 |
|
240 aName.AssignLiteral("jump"); |
|
241 return NS_OK; |
|
242 } |
|
243 |
|
244 NS_IMETHODIMP |
|
245 XULLinkAccessible::DoAction(uint8_t aIndex) |
|
246 { |
|
247 if (aIndex != eAction_Jump) |
|
248 return NS_ERROR_INVALID_ARG; |
|
249 |
|
250 if (IsDefunct()) |
|
251 return NS_ERROR_FAILURE; |
|
252 |
|
253 DoCommand(); |
|
254 return NS_OK; |
|
255 } |
|
256 |
|
257 //////////////////////////////////////////////////////////////////////////////// |
|
258 // XULLinkAccessible: HyperLinkAccessible |
|
259 |
|
260 bool |
|
261 XULLinkAccessible::IsLink() |
|
262 { |
|
263 // Expose HyperLinkAccessible unconditionally. |
|
264 return true; |
|
265 } |
|
266 |
|
267 uint32_t |
|
268 XULLinkAccessible::StartOffset() |
|
269 { |
|
270 // If XUL link accessible is not contained by hypertext accessible then |
|
271 // start offset matches index in parent because the parent doesn't contains |
|
272 // a text. |
|
273 // XXX: accessible parent of XUL link accessible should be a hypertext |
|
274 // accessible. |
|
275 if (Accessible::IsLink()) |
|
276 return Accessible::StartOffset(); |
|
277 return IndexInParent(); |
|
278 } |
|
279 |
|
280 uint32_t |
|
281 XULLinkAccessible::EndOffset() |
|
282 { |
|
283 if (Accessible::IsLink()) |
|
284 return Accessible::EndOffset(); |
|
285 return IndexInParent() + 1; |
|
286 } |
|
287 |
|
288 already_AddRefed<nsIURI> |
|
289 XULLinkAccessible::AnchorURIAt(uint32_t aAnchorIndex) |
|
290 { |
|
291 if (aAnchorIndex != 0) |
|
292 return nullptr; |
|
293 |
|
294 nsAutoString href; |
|
295 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href); |
|
296 |
|
297 nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI(); |
|
298 nsIDocument* document = mContent->OwnerDoc(); |
|
299 |
|
300 nsCOMPtr<nsIURI> anchorURI; |
|
301 NS_NewURI(getter_AddRefs(anchorURI), href, |
|
302 document->GetDocumentCharacterSet().get(), |
|
303 baseURI); |
|
304 |
|
305 return anchorURI.forget(); |
|
306 } |