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