/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef __nsAccessibilityService_h__ #define __nsAccessibilityService_h__ #include "mozilla/a11y/DocManager.h" #include "mozilla/a11y/FocusManager.h" #include "mozilla/a11y/Platform.h" #include "mozilla/a11y/Role.h" #include "mozilla/a11y/SelectionManager.h" #include "mozilla/Preferences.h" #include "nsIContent.h" #include "nsIObserver.h" #include "nsIAccessibleEvent.h" #include "nsIEventListenerService.h" #include "nsXULAppAPI.h" #include "xpcAccessibilityService.h" class nsImageFrame; class nsIArray; class nsIPersistentProperties; class nsPluginFrame; class nsITreeView; namespace mozilla { class PresShell; namespace dom { class DOMStringList; class Element; } // namespace dom namespace a11y { class ApplicationAccessible; class xpcAccessibleApplication; /** * Return focus manager. */ FocusManager* FocusMgr(); /** * Return selection manager. */ SelectionManager* SelectionMgr(); /** * Returns the application accessible. */ ApplicationAccessible* ApplicationAcc(); xpcAccessibleApplication* XPCApplicationAcc(); typedef Accessible*(New_Accessible)(mozilla::dom::Element* aElement, Accessible* aContext); // These fields are not `nsStaticAtom* const` because MSVC doesn't like it. struct MarkupAttrInfo { nsStaticAtom* name; nsStaticAtom* value; nsStaticAtom* DOMAttrName; nsStaticAtom* DOMAttrValue; }; struct HTMLMarkupMapInfo { const nsStaticAtom* const tag; New_Accessible* new_func; a11y::role role; MarkupAttrInfo attrs[4]; }; #ifdef MOZ_XUL struct XULMarkupMapInfo { const nsStaticAtom* const tag; New_Accessible* new_func; }; #endif /** * PREF_ACCESSIBILITY_FORCE_DISABLED preference change callback. */ void PrefChanged(const char* aPref, void* aClosure); /** * Read and normalize PREF_ACCESSIBILITY_FORCE_DISABLED preference. */ EPlatformDisabledState ReadPlatformDisabledState(); } // namespace a11y } // namespace mozilla class nsAccessibilityService final : public mozilla::a11y::DocManager, public mozilla::a11y::FocusManager, public mozilla::a11y::SelectionManager, public nsIListenerChangeListener, public nsIObserver { public: typedef mozilla::a11y::Accessible Accessible; typedef mozilla::a11y::DocAccessible DocAccessible; // nsIListenerChangeListener NS_IMETHOD ListenersChanged(nsIArray* aEventChanges) override; protected: ~nsAccessibilityService(); public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIOBSERVER Accessible* GetRootDocumentAccessible(mozilla::PresShell* aPresShell, bool aCanCreate); already_AddRefed CreatePluginAccessible(nsPluginFrame* aFrame, nsIContent* aContent, Accessible* aContext); /** * Adds/remove ATK root accessible for gtk+ native window to/from children * of the application accessible. */ Accessible* AddNativeRootAccessible(void* aAtkAccessible); void RemoveNativeRootAccessible(Accessible* aRootAccessible); bool HasAccessible(nsINode* aDOMNode); /** * Get a string equivalent for an accessible role value. */ void GetStringRole(uint32_t aRole, nsAString& aString); /** * Get a string equivalent for an accessible state/extra state. */ already_AddRefed GetStringStates( uint64_t aStates) const; void GetStringStates(uint32_t aState, uint32_t aExtraState, nsISupports** aStringStates); /** * Get a string equivalent for an accessible event value. */ void GetStringEventType(uint32_t aEventType, nsAString& aString); /** * Get a string equivalent for an accessible event value. */ void GetStringEventType(uint32_t aEventType, nsACString& aString); /** * Get a string equivalent for an accessible relation type. */ void GetStringRelationType(uint32_t aRelationType, nsAString& aString); // nsAccesibilityService /** * Notification used to update the accessible tree when deck panel is * switched. */ void DeckPanelSwitched(mozilla::PresShell* aPresShell, nsIContent* aDeckNode, nsIFrame* aPrevBoxFrame, nsIFrame* aCurrentBoxFrame); /** * Notification used to update the accessible tree when new content is * inserted. */ void ContentRangeInserted(mozilla::PresShell* aPresShell, nsIContent* aStartChild, nsIContent* aEndChild); /** * Notification used to update the accessible tree when content is removed. */ void ContentRemoved(mozilla::PresShell* aPresShell, nsIContent* aChild); void UpdateText(mozilla::PresShell* aPresShell, nsIContent* aContent); /** * Update XUL:tree accessible tree when treeview is changed. */ void TreeViewChanged(mozilla::PresShell* aPresShell, nsIContent* aContent, nsITreeView* aView); /** * Notify of input@type="element" value change. */ void RangeValueChanged(mozilla::PresShell* aPresShell, nsIContent* aContent); /** * Update list bullet accessible. */ void UpdateListBullet(mozilla::PresShell* aPresShell, nsIContent* aHTMLListItemContent, bool aHasBullet); /** * Update the image map. */ void UpdateImageMap(nsImageFrame* aImageFrame); /** * Update the label accessible tree when rendered @value is changed. */ void UpdateLabelValue(mozilla::PresShell* aPresShell, nsIContent* aLabelElm, const nsString& aNewValue); /** * Notify accessibility that anchor jump has been accomplished to the given * target. Used by layout. */ void NotifyOfAnchorJumpTo(nsIContent* aTarget); /** * Notify that presshell is activated. */ void PresShellActivated(mozilla::PresShell* aPresShell); /** * Recreate an accessible for the given content node in the presshell. */ void RecreateAccessible(mozilla::PresShell* aPresShell, nsIContent* aContent); void FireAccessibleEvent(uint32_t aEvent, Accessible* aTarget); /** * Notify accessibility that the size has become available for an image. * This occurs when the size of an image is initially not known, but we've * now loaded enough data to know the size. * Called by layout. */ void NotifyOfImageSizeAvailable(mozilla::PresShell* aPresShell, nsIContent* aContent); // nsAccessibiltiyService /** * Return true if accessibility service has been shutdown. */ static bool IsShutdown() { return gConsumers == 0; }; /** * Creates an accessible for the given DOM node. * * @param aNode [in] the given node * @param aContext [in] context the accessible is created in * @param aIsSubtreeHidden [out, optional] indicates whether the node's * frame and its subtree is hidden */ Accessible* CreateAccessible(nsINode* aNode, Accessible* aContext, bool* aIsSubtreeHidden = nullptr); mozilla::a11y::role MarkupRole(const nsIContent* aContent) const { const mozilla::a11y::HTMLMarkupMapInfo* markupMap = mHTMLMarkupMap.Get(aContent->NodeInfo()->NameAtom()); return markupMap ? markupMap->role : mozilla::a11y::roles::NOTHING; } /** * Return the associated value for a given attribute if * it appears in the MarkupMap. Otherwise, it returns null. */ nsStaticAtom* MarkupAttribute(const nsIContent* aContent, nsStaticAtom* aAtom) const { const mozilla::a11y::HTMLMarkupMapInfo* markupMap = mHTMLMarkupMap.Get(aContent->NodeInfo()->NameAtom()); if (markupMap) { for (size_t i = 0; i < mozilla::ArrayLength(markupMap->attrs); i++) { const mozilla::a11y::MarkupAttrInfo* info = markupMap->attrs + i; if (info->name == aAtom) { return info->value; } } } return nullptr; } /** * Set the object attribute defined by markup for the given element. */ void MarkupAttributes(const nsIContent* aContent, nsIPersistentProperties* aAttributes) const; /** * A list of possible accessibility service consumers. Accessibility service * can only be shut down when there are no remaining consumers. * * eXPCOM - accessibility service is used by XPCOM. * * eMainProcess - accessibility service was started by main process in the * content process. * * ePlatformAPI - accessibility service is used by the platform api in the * main process. */ enum ServiceConsumer { eXPCOM = 1 << 0, eMainProcess = 1 << 1, ePlatformAPI = 1 << 2, }; private: // nsAccessibilityService creation is controlled by friend // GetOrCreateAccService, keep constructors private. nsAccessibilityService(); nsAccessibilityService(const nsAccessibilityService&); nsAccessibilityService& operator=(const nsAccessibilityService&); private: /** * Initialize accessibility service. */ bool Init(); /** * Shutdowns accessibility service. */ void Shutdown(); /** * Create an accessible whose type depends on the given frame. */ already_AddRefed CreateAccessibleByFrameType( nsIFrame* aFrame, nsIContent* aContent, Accessible* aContext); /** * Notify observers about change of the accessibility service's consumers. */ void NotifyOfConsumersChange(); /** * Get a JSON string representing the accessibility service consumers. */ void GetConsumers(nsAString& aString); /** * Set accessibility service consumers. */ void SetConsumers(uint32_t aConsumers, bool aNotify = true); /** * Unset accessibility service consumers. */ void UnsetConsumers(uint32_t aConsumers); /** * Reference for accessibility service instance. */ static nsAccessibilityService* gAccessibilityService; /** * Reference for application accessible instance. */ static mozilla::a11y::ApplicationAccessible* gApplicationAccessible; static mozilla::a11y::xpcAccessibleApplication* gXPCApplicationAccessible; /** * Contains a set of accessibility service consumers. */ static uint32_t gConsumers; nsDataHashtable, const mozilla::a11y::HTMLMarkupMapInfo*> mHTMLMarkupMap; #ifdef MOZ_XUL nsDataHashtable, const mozilla::a11y::XULMarkupMapInfo*> mXULMarkupMap; #endif friend nsAccessibilityService* GetAccService(); friend nsAccessibilityService* GetOrCreateAccService(uint32_t); friend void MaybeShutdownAccService(uint32_t); friend void mozilla::a11y::PrefChanged(const char*, void*); friend mozilla::a11y::FocusManager* mozilla::a11y::FocusMgr(); friend mozilla::a11y::SelectionManager* mozilla::a11y::SelectionMgr(); friend mozilla::a11y::ApplicationAccessible* mozilla::a11y::ApplicationAcc(); friend mozilla::a11y::xpcAccessibleApplication* mozilla::a11y::XPCApplicationAcc(); friend class xpcAccessibilityService; }; /** * Return the accessibility service instance. (Handy global function) */ inline nsAccessibilityService* GetAccService() { return nsAccessibilityService::gAccessibilityService; } /** * Return accessibility service instance; creating one if necessary. */ nsAccessibilityService* GetOrCreateAccService( uint32_t aNewConsumer = nsAccessibilityService::ePlatformAPI); /** * Shutdown accessibility service if needed. */ void MaybeShutdownAccService(uint32_t aFormerConsumer); /** * Return true if we're in a content process and not B2G. */ inline bool IPCAccessibilityActive() { return XRE_IsContentProcess(); } /** * Map nsIAccessibleEvents constants to strings. Used by * nsAccessibilityService::GetStringEventType() method. */ static const char kEventTypeNames[][40] = { "unknown", // "show", // EVENT_SHOW "hide", // EVENT_HIDE "reorder", // EVENT_REORDER "active decendent change", // EVENT_ACTIVE_DECENDENT_CHANGED "focus", // EVENT_FOCUS "state change", // EVENT_STATE_CHANGE "location change", // EVENT_LOCATION_CHANGE "name changed", // EVENT_NAME_CHANGE "description change", // EVENT_DESCRIPTION_CHANGE "value change", // EVENT_VALUE_CHANGE "help change", // EVENT_HELP_CHANGE "default action change", // EVENT_DEFACTION_CHANGE "action change", // EVENT_ACTION_CHANGE "accelerator change", // EVENT_ACCELERATOR_CHANGE "selection", // EVENT_SELECTION "selection add", // EVENT_SELECTION_ADD "selection remove", // EVENT_SELECTION_REMOVE "selection within", // EVENT_SELECTION_WITHIN "alert", // EVENT_ALERT "foreground", // EVENT_FOREGROUND "menu start", // EVENT_MENU_START "menu end", // EVENT_MENU_END "menupopup start", // EVENT_MENUPOPUP_START "menupopup end", // EVENT_MENUPOPUP_END "capture start", // EVENT_CAPTURE_START "capture end", // EVENT_CAPTURE_END "movesize start", // EVENT_MOVESIZE_START "movesize end", // EVENT_MOVESIZE_END "contexthelp start", // EVENT_CONTEXTHELP_START "contexthelp end", // EVENT_CONTEXTHELP_END "dragdrop start", // EVENT_DRAGDROP_START "dragdrop end", // EVENT_DRAGDROP_END "dialog start", // EVENT_DIALOG_START "dialog end", // EVENT_DIALOG_END "scrolling start", // EVENT_SCROLLING_START "scrolling end", // EVENT_SCROLLING_END "minimize start", // EVENT_MINIMIZE_START "minimize end", // EVENT_MINIMIZE_END "document load complete", // EVENT_DOCUMENT_LOAD_COMPLETE "document reload", // EVENT_DOCUMENT_RELOAD "document load stopped", // EVENT_DOCUMENT_LOAD_STOPPED "document attributes changed", // EVENT_DOCUMENT_ATTRIBUTES_CHANGED "document content changed", // EVENT_DOCUMENT_CONTENT_CHANGED "property changed", // EVENT_PROPERTY_CHANGED "page changed", // EVENT_PAGE_CHANGED "text attribute changed", // EVENT_TEXT_ATTRIBUTE_CHANGED "text caret moved", // EVENT_TEXT_CARET_MOVED "text changed", // EVENT_TEXT_CHANGED "text inserted", // EVENT_TEXT_INSERTED "text removed", // EVENT_TEXT_REMOVED "text updated", // EVENT_TEXT_UPDATED "text selection changed", // EVENT_TEXT_SELECTION_CHANGED "visible data changed", // EVENT_VISIBLE_DATA_CHANGED "text column changed", // EVENT_TEXT_COLUMN_CHANGED "section changed", // EVENT_SECTION_CHANGED "table caption changed", // EVENT_TABLE_CAPTION_CHANGED "table model changed", // EVENT_TABLE_MODEL_CHANGED "table summary changed", // EVENT_TABLE_SUMMARY_CHANGED "table row description changed", // EVENT_TABLE_ROW_DESCRIPTION_CHANGED "table row header changed", // EVENT_TABLE_ROW_HEADER_CHANGED "table row insert", // EVENT_TABLE_ROW_INSERT "table row delete", // EVENT_TABLE_ROW_DELETE "table row reorder", // EVENT_TABLE_ROW_REORDER "table column description changed", // EVENT_TABLE_COLUMN_DESCRIPTION_CHANGED "table column header changed", // EVENT_TABLE_COLUMN_HEADER_CHANGED "table column insert", // EVENT_TABLE_COLUMN_INSERT "table column delete", // EVENT_TABLE_COLUMN_DELETE "table column reorder", // EVENT_TABLE_COLUMN_REORDER "window activate", // EVENT_WINDOW_ACTIVATE "window create", // EVENT_WINDOW_CREATE "window deactivate", // EVENT_WINDOW_DEACTIVATE "window destroy", // EVENT_WINDOW_DESTROY "window maximize", // EVENT_WINDOW_MAXIMIZE "window minimize", // EVENT_WINDOW_MINIMIZE "window resize", // EVENT_WINDOW_RESIZE "window restore", // EVENT_WINDOW_RESTORE "hyperlink end index changed", // EVENT_HYPERLINK_END_INDEX_CHANGED "hyperlink number of anchors changed", // EVENT_HYPERLINK_NUMBER_OF_ANCHORS_CHANGED "hyperlink selected link changed", // EVENT_HYPERLINK_SELECTED_LINK_CHANGED "hypertext link activated", // EVENT_HYPERTEXT_LINK_ACTIVATED "hypertext link selected", // EVENT_HYPERTEXT_LINK_SELECTED "hyperlink start index changed", // EVENT_HYPERLINK_START_INDEX_CHANGED "hypertext changed", // EVENT_HYPERTEXT_CHANGED "hypertext links count changed", // EVENT_HYPERTEXT_NLINKS_CHANGED "object attribute changed", // EVENT_OBJECT_ATTRIBUTE_CHANGED "virtual cursor changed", // EVENT_VIRTUALCURSOR_CHANGED "text value change", // EVENT_TEXT_VALUE_CHANGE "scrolling", // EVENT_SCROLLING "announcement", // EVENT_ANNOUNCEMENT "live region added", // EVENT_LIVE_REGION_ADDED "live region removed", // EVENT_LIVE_REGION_REMOVED }; #endif