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 #ifndef MOZILLA_A11Y_HTMLFormControlAccessible_H_
7 #define MOZILLA_A11Y_HTMLFormControlAccessible_H_
8 
9 #include "FormControlAccessible.h"
10 #include "HyperTextAccessibleWrap.h"
11 #include "nsAccUtils.h"
12 #include "Relation.h"
13 
14 namespace mozilla {
15 class TextEditor;
16 namespace a11y {
17 
18 /**
19  * Accessible for HTML input@type="radio" element.
20  */
21 class HTMLRadioButtonAccessible : public RadioButtonAccessible {
22  public:
HTMLRadioButtonAccessible(nsIContent * aContent,DocAccessible * aDoc)23   HTMLRadioButtonAccessible(nsIContent* aContent, DocAccessible* aDoc)
24       : RadioButtonAccessible(aContent, aDoc) {
25     // Ignore "RadioStateChange" DOM event in lieu of document observer
26     // state change notification.
27     mStateFlags |= eIgnoreDOMUIEvent;
28   }
29 
30   // Accessible
31   virtual uint64_t NativeState() const override;
32   virtual void GetPositionAndSizeInternal(int32_t* aPosInSet,
33                                           int32_t* aSetSize) override;
34   virtual Relation RelationByType(RelationType aType) const override;
35 
36  private:
37   Relation ComputeGroupAttributes(int32_t* aPosInSet, int32_t* aSetSize) const;
38 };
39 
40 /**
41  * Accessible for HTML input@type="button", @type="submit", @type="image"
42  * and HTML button elements.
43  */
44 class HTMLButtonAccessible : public HyperTextAccessibleWrap {
45  public:
46   enum { eAction_Click = 0 };
47 
48   HTMLButtonAccessible(nsIContent* aContent, DocAccessible* aDoc);
49 
50   // Accessible
51   virtual mozilla::a11y::role NativeRole() const override;
52   virtual uint64_t State() override;
53   virtual uint64_t NativeState() const override;
54 
55   // ActionAccessible
56   virtual uint8_t ActionCount() const override;
57   virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;
58   virtual bool DoAction(uint8_t aIndex) const override;
59 
60   // Widgets
61   virtual bool IsWidget() const override;
62 
63  protected:
64   // Accessible
65   virtual ENameValueFlag NativeName(nsString& aName) const override;
66 };
67 
68 /**
69  * Accessible for HTML input@type="text", input@type="password", textarea and
70  * other HTML text controls.
71  */
72 class HTMLTextFieldAccessible : public HyperTextAccessibleWrap {
73  public:
74   enum { eAction_Click = 0 };
75 
76   HTMLTextFieldAccessible(nsIContent* aContent, DocAccessible* aDoc);
77 
78   NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLTextFieldAccessible,
79                                        HyperTextAccessibleWrap)
80 
81   // HyperTextAccessible
82   MOZ_CAN_RUN_SCRIPT_BOUNDARY virtual already_AddRefed<TextEditor> GetEditor()
83       const override;
84 
85   // Accessible
86   virtual void Value(nsString& aValue) const override;
87   virtual void ApplyARIAState(uint64_t* aState) const override;
88   virtual mozilla::a11y::role NativeRole() const override;
89   virtual uint64_t NativeState() const override;
90   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes() override;
91 
92   // ActionAccessible
93   virtual uint8_t ActionCount() const override;
94   virtual void ActionNameAt(uint8_t aIndex, nsAString& aName) override;
95   virtual bool DoAction(uint8_t aIndex) const override;
96 
97   // Widgets
98   virtual bool IsWidget() const override;
99   virtual Accessible* ContainerWidget() const override;
100 
101  protected:
~HTMLTextFieldAccessible()102   virtual ~HTMLTextFieldAccessible() {}
103 
104   // Accessible
105   virtual ENameValueFlag NativeName(nsString& aName) const override;
106 
107   /**
108    * Return a widget element this input is part of, for example, search-textbox.
109    *
110    * FIXME: This should probably be renamed.
111    */
BindingOrWidgetParent()112   nsIContent* BindingOrWidgetParent() const {
113     if (auto* el = mContent->GetClosestNativeAnonymousSubtreeRootParent()) {
114       return el;
115     }
116     // XUL search-textbox custom element
117     return Elm()->Closest(NS_LITERAL_STRING("search-textbox"), IgnoreErrors());
118   }
119 };
120 
121 /**
122  * Accessible for input@type="file" element.
123  */
124 class HTMLFileInputAccessible : public HyperTextAccessibleWrap {
125  public:
126   HTMLFileInputAccessible(nsIContent* aContent, DocAccessible* aDoc);
127 
128   // Accessible
129   virtual mozilla::a11y::role NativeRole() const override;
130   virtual nsresult HandleAccEvent(AccEvent* aAccEvent) override;
131   virtual Accessible* CurrentItem() const override;
132 };
133 
134 /**
135  * Used for HTML input@type="number".
136  */
137 class HTMLSpinnerAccessible final : public HTMLTextFieldAccessible {
138  public:
HTMLSpinnerAccessible(nsIContent * aContent,DocAccessible * aDoc)139   HTMLSpinnerAccessible(nsIContent* aContent, DocAccessible* aDoc)
140       : HTMLTextFieldAccessible(aContent, aDoc) {
141     mStateFlags |= eHasNumericValue;
142   }
143 
144   // Accessible
145   virtual mozilla::a11y::role NativeRole() const override;
146   virtual void Value(nsString& aValue) const override;
147 
148   virtual double MaxValue() const override;
149   virtual double MinValue() const override;
150   virtual double CurValue() const override;
151   virtual double Step() const override;
152   virtual bool SetCurValue(double aValue) override;
153 };
154 
155 /**
156  * Used for input@type="range" element.
157  */
158 class HTMLRangeAccessible : public LeafAccessible {
159  public:
HTMLRangeAccessible(nsIContent * aContent,DocAccessible * aDoc)160   HTMLRangeAccessible(nsIContent* aContent, DocAccessible* aDoc)
161       : LeafAccessible(aContent, aDoc) {
162     mStateFlags |= eHasNumericValue;
163   }
164 
165   // Accessible
166   virtual void Value(nsString& aValue) const override;
167   virtual mozilla::a11y::role NativeRole() const override;
168 
169   // Value
170   virtual double MaxValue() const override;
171   virtual double MinValue() const override;
172   virtual double CurValue() const override;
173   virtual double Step() const override;
174   virtual bool SetCurValue(double aValue) override;
175 
176   // Widgets
177   virtual bool IsWidget() const override;
178 };
179 
180 /**
181  * Accessible for HTML fieldset element.
182  */
183 class HTMLGroupboxAccessible : public HyperTextAccessibleWrap {
184  public:
185   HTMLGroupboxAccessible(nsIContent* aContent, DocAccessible* aDoc);
186 
187   // Accessible
188   virtual mozilla::a11y::role NativeRole() const override;
189   virtual Relation RelationByType(RelationType aType) const override;
190 
191  protected:
192   // Accessible
193   virtual ENameValueFlag NativeName(nsString& aName) const override;
194 
195   // HTMLGroupboxAccessible
196   nsIContent* GetLegend() const;
197 };
198 
199 /**
200  * Accessible for HTML legend element.
201  */
202 class HTMLLegendAccessible : public HyperTextAccessibleWrap {
203  public:
204   HTMLLegendAccessible(nsIContent* aContent, DocAccessible* aDoc);
205 
206   // Accessible
207   virtual Relation RelationByType(RelationType aType) const override;
208 };
209 
210 /**
211  * Accessible for HTML5 figure element.
212  */
213 class HTMLFigureAccessible : public HyperTextAccessibleWrap {
214  public:
215   HTMLFigureAccessible(nsIContent* aContent, DocAccessible* aDoc);
216 
217   // Accessible
218   virtual Relation RelationByType(RelationType aType) const override;
219 
220  protected:
221   // Accessible
222   virtual ENameValueFlag NativeName(nsString& aName) const override;
223 
224   // HTMLLegendAccessible
225   nsIContent* Caption() const;
226 };
227 
228 /**
229  * Accessible for HTML5 figcaption element.
230  */
231 class HTMLFigcaptionAccessible : public HyperTextAccessibleWrap {
232  public:
233   HTMLFigcaptionAccessible(nsIContent* aContent, DocAccessible* aDoc);
234 
235   // Accessible
236   virtual Relation RelationByType(RelationType aType) const override;
237 };
238 
239 /**
240  * Used for HTML form element.
241  */
242 class HTMLFormAccessible : public HyperTextAccessibleWrap {
243  public:
HTMLFormAccessible(nsIContent * aContent,DocAccessible * aDoc)244   HTMLFormAccessible(nsIContent* aContent, DocAccessible* aDoc)
245       : HyperTextAccessibleWrap(aContent, aDoc) {}
246 
247   NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLFormAccessible,
248                                        HyperTextAccessibleWrap)
249 
250   // Accessible
251   virtual nsAtom* LandmarkRole() const override;
252   virtual a11y::role NativeRole() const override;
253 
254  protected:
255   virtual ~HTMLFormAccessible() = default;
256 };
257 
258 /**
259  * Accessible for HTML progress element.
260  */
261 
262 class HTMLProgressAccessible : public LeafAccessible {
263  public:
HTMLProgressAccessible(nsIContent * aContent,DocAccessible * aDoc)264   HTMLProgressAccessible(nsIContent* aContent, DocAccessible* aDoc)
265       : LeafAccessible(aContent, aDoc) {
266     // Ignore 'ValueChange' DOM event in lieu of @value attribute change
267     // notifications.
268     mStateFlags |= eHasNumericValue | eIgnoreDOMUIEvent;
269     mType = eProgressType;
270   }
271 
272   // Accessible
273   virtual void Value(nsString& aValue) const override;
274   virtual mozilla::a11y::role NativeRole() const override;
275   virtual uint64_t NativeState() const override;
276 
277   // Value
278   virtual double MaxValue() const override;
279   virtual double MinValue() const override;
280   virtual double CurValue() const override;
281   virtual double Step() const override;
282   virtual bool SetCurValue(double aValue) override;
283 
284   // Widgets
285   virtual bool IsWidget() const override;
286 
287  protected:
~HTMLProgressAccessible()288   virtual ~HTMLProgressAccessible() {}
289 };
290 
291 /**
292  * Accessible for HTML date/time inputs.
293  */
294 template <a11y::role R>
295 class HTMLDateTimeAccessible : public AccessibleWrap {
296  public:
HTMLDateTimeAccessible(nsIContent * aContent,DocAccessible * aDoc)297   HTMLDateTimeAccessible(nsIContent* aContent, DocAccessible* aDoc)
298       : AccessibleWrap(aContent, aDoc) {}
299 
NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLDateTimeAccessible,AccessibleWrap)300   NS_INLINE_DECL_REFCOUNTING_INHERITED(HTMLDateTimeAccessible, AccessibleWrap)
301 
302   // Accessible
303   virtual mozilla::a11y::role NativeRole() const override { return R; }
NativeAttributes()304   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes()
305       override {
306     nsCOMPtr<nsIPersistentProperties> attributes =
307         AccessibleWrap::NativeAttributes();
308     // Unfortunately, an nsStaticAtom can't be passed as a
309     // template argument, so fetch the type from the DOM.
310     nsAutoString type;
311     if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
312                                        type)) {
313       nsAccUtils::SetAccAttr(attributes, nsGkAtoms::textInputType, type);
314     }
315     return attributes.forget();
316   }
317 
318   // Widgets
IsWidget()319   virtual bool IsWidget() const override { return true; }
320 
321  protected:
~HTMLDateTimeAccessible()322   virtual ~HTMLDateTimeAccessible() {}
323 };
324 
325 }  // namespace a11y
326 }  // namespace mozilla
327 
328 #endif
329