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 __nsAccessibilityService_h__
7 #define __nsAccessibilityService_h__
8
9 #include "mozilla/a11y/DocManager.h"
10 #include "mozilla/a11y/FocusManager.h"
11 #include "mozilla/a11y/Platform.h"
12 #include "mozilla/a11y/Role.h"
13 #include "mozilla/a11y/SelectionManager.h"
14 #include "mozilla/Preferences.h"
15
16 #include "nsIObserver.h"
17 #include "nsIAccessibleEvent.h"
18 #include "nsIEventListenerService.h"
19 #include "xpcAccessibilityService.h"
20
21 class nsImageFrame;
22 class nsIArray;
23 class nsIPersistentProperties;
24 class nsPluginFrame;
25 class nsITreeView;
26
27 namespace mozilla {
28
29 namespace dom {
30 class DOMStringList;
31 }
32
33 namespace a11y {
34
35 class ApplicationAccessible;
36 class xpcAccessibleApplication;
37
38 /**
39 * Return focus manager.
40 */
41 FocusManager* FocusMgr();
42
43 /**
44 * Return selection manager.
45 */
46 SelectionManager* SelectionMgr();
47
48 /**
49 * Returns the application accessible.
50 */
51 ApplicationAccessible* ApplicationAcc();
52 xpcAccessibleApplication* XPCApplicationAcc();
53
54 typedef Accessible*(New_Accessible)(nsIContent* aContent, Accessible* aContext);
55
56 struct MarkupAttrInfo {
57 nsStaticAtom** name;
58 nsStaticAtom** value;
59
60 nsStaticAtom** DOMAttrName;
61 nsStaticAtom** DOMAttrValue;
62 };
63
64 struct HTMLMarkupMapInfo {
65 nsStaticAtom** tag;
66 New_Accessible* new_func;
67 a11y::role role;
68 MarkupAttrInfo attrs[4];
69 };
70
71 #ifdef MOZ_XUL
72 struct XULMarkupMapInfo {
73 nsStaticAtom** tag;
74 New_Accessible* new_func;
75 };
76 #endif
77
78 /**
79 * PREF_ACCESSIBILITY_FORCE_DISABLED preference change callback.
80 */
81 void PrefChanged(const char* aPref, void* aClosure);
82
83 /**
84 * Read and normalize PREF_ACCESSIBILITY_FORCE_DISABLED preference.
85 */
86 EPlatformDisabledState ReadPlatformDisabledState();
87
88 } // namespace a11y
89 } // namespace mozilla
90
91 class nsAccessibilityService final : public mozilla::a11y::DocManager,
92 public mozilla::a11y::FocusManager,
93 public mozilla::a11y::SelectionManager,
94 public nsIListenerChangeListener,
95 public nsIObserver {
96 public:
97 typedef mozilla::a11y::Accessible Accessible;
98 typedef mozilla::a11y::DocAccessible DocAccessible;
99
100 // nsIListenerChangeListener
101 NS_IMETHOD ListenersChanged(nsIArray* aEventChanges) override;
102
103 protected:
104 ~nsAccessibilityService();
105
106 public:
107 NS_DECL_ISUPPORTS_INHERITED
108 NS_DECL_NSIOBSERVER
109
110 Accessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
111 bool aCanCreate);
112 already_AddRefed<Accessible> CreatePluginAccessible(nsPluginFrame* aFrame,
113 nsIContent* aContent,
114 Accessible* aContext);
115
116 /**
117 * Adds/remove ATK root accessible for gtk+ native window to/from children
118 * of the application accessible.
119 */
120 Accessible* AddNativeRootAccessible(void* aAtkAccessible);
121 void RemoveNativeRootAccessible(Accessible* aRootAccessible);
122
123 bool HasAccessible(nsIDOMNode* aDOMNode);
124
125 /**
126 * Get a string equivalent for an accessible role value.
127 */
128 void GetStringRole(uint32_t aRole, nsAString& aString);
129
130 /**
131 * Get a string equivalent for an accessible state/extra state.
132 */
133 already_AddRefed<mozilla::dom::DOMStringList> GetStringStates(
134 uint64_t aStates) const;
135 void GetStringStates(uint32_t aState, uint32_t aExtraState,
136 nsISupports** aStringStates);
137
138 /**
139 * Get a string equivalent for an accessible event value.
140 */
141 void GetStringEventType(uint32_t aEventType, nsAString& aString);
142
143 /**
144 * Get a string equivalent for an accessible event value.
145 */
146 void GetStringEventType(uint32_t aEventType, nsACString& aString);
147
148 /**
149 * Get a string equivalent for an accessible relation type.
150 */
151 void GetStringRelationType(uint32_t aRelationType, nsAString& aString);
152
153 // nsAccesibilityService
154 /**
155 * Notification used to update the accessible tree when deck panel is
156 * switched.
157 */
158 void DeckPanelSwitched(nsIPresShell* aPresShell, nsIContent* aDeckNode,
159 nsIFrame* aPrevBoxFrame, nsIFrame* aCurrentBoxFrame);
160
161 /**
162 * Notification used to update the accessible tree when new content is
163 * inserted.
164 */
165 void ContentRangeInserted(nsIPresShell* aPresShell, nsIContent* aContainer,
166 nsIContent* aStartChild, nsIContent* aEndChild);
167
168 /**
169 * Notification used to update the accessible tree when content is removed.
170 */
171 void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aChild);
172
173 void UpdateText(nsIPresShell* aPresShell, nsIContent* aContent);
174
175 /**
176 * Update XUL:tree accessible tree when treeview is changed.
177 */
178 void TreeViewChanged(nsIPresShell* aPresShell, nsIContent* aContent,
179 nsITreeView* aView);
180
181 /**
182 * Notify of input@type="element" value change.
183 */
184 void RangeValueChanged(nsIPresShell* aPresShell, nsIContent* aContent);
185
186 /**
187 * Update list bullet accessible.
188 */
189 void UpdateListBullet(nsIPresShell* aPresShell,
190 nsIContent* aHTMLListItemContent, bool aHasBullet);
191
192 /**
193 * Update the image map.
194 */
195 void UpdateImageMap(nsImageFrame* aImageFrame);
196
197 /**
198 * Update the label accessible tree when rendered @value is changed.
199 */
200 void UpdateLabelValue(nsIPresShell* aPresShell, nsIContent* aLabelElm,
201 const nsString& aNewValue);
202
203 /**
204 * Notify accessibility that anchor jump has been accomplished to the given
205 * target. Used by layout.
206 */
207 void NotifyOfAnchorJumpTo(nsIContent* aTarget);
208
209 /**
210 * Notify that presshell is activated.
211 */
212 void PresShellActivated(nsIPresShell* aPresShell);
213
214 /**
215 * Recreate an accessible for the given content node in the presshell.
216 */
217 void RecreateAccessible(nsIPresShell* aPresShell, nsIContent* aContent);
218
219 void FireAccessibleEvent(uint32_t aEvent, Accessible* aTarget);
220
221 // nsAccessibiltiyService
222
223 /**
224 * Return true if accessibility service has been shutdown.
225 */
IsShutdown()226 static bool IsShutdown() { return gConsumers == 0; };
227
228 /**
229 * Creates an accessible for the given DOM node.
230 *
231 * @param aNode [in] the given node
232 * @param aContext [in] context the accessible is created in
233 * @param aIsSubtreeHidden [out, optional] indicates whether the node's
234 * frame and its subtree is hidden
235 */
236 Accessible* CreateAccessible(nsINode* aNode, Accessible* aContext,
237 bool* aIsSubtreeHidden = nullptr);
238
MarkupRole(const nsIContent * aContent)239 mozilla::a11y::role MarkupRole(const nsIContent* aContent) const {
240 const mozilla::a11y::HTMLMarkupMapInfo* markupMap =
241 mHTMLMarkupMap.Get(aContent->NodeInfo()->NameAtom());
242 return markupMap ? markupMap->role : mozilla::a11y::roles::NOTHING;
243 }
244
245 /**
246 * Set the object attribute defined by markup for the given element.
247 */
248 void MarkupAttributes(const nsIContent* aContent,
249 nsIPersistentProperties* aAttributes) const;
250
251 /**
252 * A list of possible accessibility service consumers. Accessibility service
253 * can only be shut down when there are no remaining consumers.
254 *
255 * eXPCOM - accessibility service is used by XPCOM.
256 *
257 * eMainProcess - accessibility service was started by main process in the
258 * content process.
259 *
260 * ePlatformAPI - accessibility service is used by the platform api in the
261 * main process.
262 */
263 enum ServiceConsumer {
264 eXPCOM = 1 << 0,
265 eMainProcess = 1 << 1,
266 ePlatformAPI = 1 << 2,
267 };
268
269 private:
270 // nsAccessibilityService creation is controlled by friend
271 // GetOrCreateAccService, keep constructors private.
272 nsAccessibilityService();
273 nsAccessibilityService(const nsAccessibilityService&);
274 nsAccessibilityService& operator=(const nsAccessibilityService&);
275
276 private:
277 /**
278 * Initialize accessibility service.
279 */
280 bool Init();
281
282 /**
283 * Shutdowns accessibility service.
284 */
285 void Shutdown();
286
287 /**
288 * Create an accessible whose type depends on the given frame.
289 */
290 already_AddRefed<Accessible> CreateAccessibleByFrameType(
291 nsIFrame* aFrame, nsIContent* aContent, Accessible* aContext);
292
293 /**
294 * Notify observers about change of the accessibility service's consumers.
295 */
296 void NotifyOfConsumersChange();
297
298 /**
299 * Get a JSON string representing the accessibility service consumers.
300 */
301 void GetConsumers(nsAString& aString);
302
303 /**
304 * Set accessibility service consumers.
305 */
306 void SetConsumers(uint32_t aConsumers, bool aNotify = true);
307
308 /**
309 * Unset accessibility service consumers.
310 */
311 void UnsetConsumers(uint32_t aConsumers);
312
313 /**
314 * Reference for accessibility service instance.
315 */
316 static nsAccessibilityService* gAccessibilityService;
317
318 /**
319 * Reference for application accessible instance.
320 */
321 static mozilla::a11y::ApplicationAccessible* gApplicationAccessible;
322 static mozilla::a11y::xpcAccessibleApplication* gXPCApplicationAccessible;
323
324 /**
325 * Contains a set of accessibility service consumers.
326 */
327 static uint32_t gConsumers;
328
329 nsDataHashtable<nsPtrHashKey<const nsAtom>,
330 const mozilla::a11y::HTMLMarkupMapInfo*>
331 mHTMLMarkupMap;
332 #ifdef MOZ_XUL
333 nsDataHashtable<nsPtrHashKey<const nsAtom>,
334 const mozilla::a11y::XULMarkupMapInfo*>
335 mXULMarkupMap;
336 #endif
337
338 friend nsAccessibilityService* GetAccService();
339 friend nsAccessibilityService* GetOrCreateAccService(uint32_t);
340 friend void MaybeShutdownAccService(uint32_t);
341 friend void mozilla::a11y::PrefChanged(const char*, void*);
342 friend mozilla::a11y::FocusManager* mozilla::a11y::FocusMgr();
343 friend mozilla::a11y::SelectionManager* mozilla::a11y::SelectionMgr();
344 friend mozilla::a11y::ApplicationAccessible* mozilla::a11y::ApplicationAcc();
345 friend mozilla::a11y::xpcAccessibleApplication*
346 mozilla::a11y::XPCApplicationAcc();
347 friend class xpcAccessibilityService;
348 };
349
350 /**
351 * Return the accessibility service instance. (Handy global function)
352 */
GetAccService()353 inline nsAccessibilityService* GetAccService() {
354 return nsAccessibilityService::gAccessibilityService;
355 }
356
357 /**
358 * Return accessibility service instance; creating one if necessary.
359 */
360 nsAccessibilityService* GetOrCreateAccService(
361 uint32_t aNewConsumer = nsAccessibilityService::ePlatformAPI);
362
363 /**
364 * Shutdown accessibility service if needed.
365 */
366 void MaybeShutdownAccService(uint32_t aFormerConsumer);
367
368 /**
369 * Return true if we're in a content process and not B2G.
370 */
IPCAccessibilityActive()371 inline bool IPCAccessibilityActive() { return XRE_IsContentProcess(); }
372
373 /**
374 * Map nsIAccessibleEvents constants to strings. Used by
375 * nsAccessibilityService::GetStringEventType() method.
376 */
377 static const char kEventTypeNames[][40] = {
378 "unknown", //
379 "show", // EVENT_SHOW
380 "hide", // EVENT_HIDE
381 "reorder", // EVENT_REORDER
382 "active decendent change", // EVENT_ACTIVE_DECENDENT_CHANGED
383 "focus", // EVENT_FOCUS
384 "state change", // EVENT_STATE_CHANGE
385 "location change", // EVENT_LOCATION_CHANGE
386 "name changed", // EVENT_NAME_CHANGE
387 "description change", // EVENT_DESCRIPTION_CHANGE
388 "value change", // EVENT_VALUE_CHANGE
389 "help change", // EVENT_HELP_CHANGE
390 "default action change", // EVENT_DEFACTION_CHANGE
391 "action change", // EVENT_ACTION_CHANGE
392 "accelerator change", // EVENT_ACCELERATOR_CHANGE
393 "selection", // EVENT_SELECTION
394 "selection add", // EVENT_SELECTION_ADD
395 "selection remove", // EVENT_SELECTION_REMOVE
396 "selection within", // EVENT_SELECTION_WITHIN
397 "alert", // EVENT_ALERT
398 "foreground", // EVENT_FOREGROUND
399 "menu start", // EVENT_MENU_START
400 "menu end", // EVENT_MENU_END
401 "menupopup start", // EVENT_MENUPOPUP_START
402 "menupopup end", // EVENT_MENUPOPUP_END
403 "capture start", // EVENT_CAPTURE_START
404 "capture end", // EVENT_CAPTURE_END
405 "movesize start", // EVENT_MOVESIZE_START
406 "movesize end", // EVENT_MOVESIZE_END
407 "contexthelp start", // EVENT_CONTEXTHELP_START
408 "contexthelp end", // EVENT_CONTEXTHELP_END
409 "dragdrop start", // EVENT_DRAGDROP_START
410 "dragdrop end", // EVENT_DRAGDROP_END
411 "dialog start", // EVENT_DIALOG_START
412 "dialog end", // EVENT_DIALOG_END
413 "scrolling start", // EVENT_SCROLLING_START
414 "scrolling end", // EVENT_SCROLLING_END
415 "minimize start", // EVENT_MINIMIZE_START
416 "minimize end", // EVENT_MINIMIZE_END
417 "document load complete", // EVENT_DOCUMENT_LOAD_COMPLETE
418 "document reload", // EVENT_DOCUMENT_RELOAD
419 "document load stopped", // EVENT_DOCUMENT_LOAD_STOPPED
420 "document attributes changed", // EVENT_DOCUMENT_ATTRIBUTES_CHANGED
421 "document content changed", // EVENT_DOCUMENT_CONTENT_CHANGED
422 "property changed", // EVENT_PROPERTY_CHANGED
423 "page changed", // EVENT_PAGE_CHANGED
424 "text attribute changed", // EVENT_TEXT_ATTRIBUTE_CHANGED
425 "text caret moved", // EVENT_TEXT_CARET_MOVED
426 "text changed", // EVENT_TEXT_CHANGED
427 "text inserted", // EVENT_TEXT_INSERTED
428 "text removed", // EVENT_TEXT_REMOVED
429 "text updated", // EVENT_TEXT_UPDATED
430 "text selection changed", // EVENT_TEXT_SELECTION_CHANGED
431 "visible data changed", // EVENT_VISIBLE_DATA_CHANGED
432 "text column changed", // EVENT_TEXT_COLUMN_CHANGED
433 "section changed", // EVENT_SECTION_CHANGED
434 "table caption changed", // EVENT_TABLE_CAPTION_CHANGED
435 "table model changed", // EVENT_TABLE_MODEL_CHANGED
436 "table summary changed", // EVENT_TABLE_SUMMARY_CHANGED
437 "table row description changed", // EVENT_TABLE_ROW_DESCRIPTION_CHANGED
438 "table row header changed", // EVENT_TABLE_ROW_HEADER_CHANGED
439 "table row insert", // EVENT_TABLE_ROW_INSERT
440 "table row delete", // EVENT_TABLE_ROW_DELETE
441 "table row reorder", // EVENT_TABLE_ROW_REORDER
442 "table column description changed", // EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED
443 "table column header changed", // EVENT_TABLE_COLUMN_HEADER_CHANGED
444 "table column insert", // EVENT_TABLE_COLUMN_INSERT
445 "table column delete", // EVENT_TABLE_COLUMN_DELETE
446 "table column reorder", // EVENT_TABLE_COLUMN_REORDER
447 "window activate", // EVENT_WINDOW_ACTIVATE
448 "window create", // EVENT_WINDOW_CREATE
449 "window deactivate", // EVENT_WINDOW_DEACTIVATE
450 "window destroy", // EVENT_WINDOW_DESTROY
451 "window maximize", // EVENT_WINDOW_MAXIMIZE
452 "window minimize", // EVENT_WINDOW_MINIMIZE
453 "window resize", // EVENT_WINDOW_RESIZE
454 "window restore", // EVENT_WINDOW_RESTORE
455 "hyperlink end index changed", // EVENT_HYPERLINK_END_INDEX_CHANGED
456 "hyperlink number of anchors changed", // EVENT_HYPERLINK_NUMBER_OF_ANCHORS_CHANGED
457 "hyperlink selected link changed", // EVENT_HYPERLINK_SELECTED_LINK_CHANGED
458 "hypertext link activated", // EVENT_HYPERTEXT_LINK_ACTIVATED
459 "hypertext link selected", // EVENT_HYPERTEXT_LINK_SELECTED
460 "hyperlink start index changed", // EVENT_HYPERLINK_START_INDEX_CHANGED
461 "hypertext changed", // EVENT_HYPERTEXT_CHANGED
462 "hypertext links count changed", // EVENT_HYPERTEXT_NLINKS_CHANGED
463 "object attribute changed", // EVENT_OBJECT_ATTRIBUTE_CHANGED
464 "virtual cursor changed", // EVENT_VIRTUALCURSOR_CHANGED
465 "text value change", // EVENT_TEXT_VALUE_CHANGE
466 };
467
468 #endif
469