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