Architecture

This document provides a high-level overview of how the accessibility code is structured. See the Document Accessibility Lifecycle page for a lower level description of the code.

Process Model

The accessibility component spans multiple processes. In the parent process, it creates an accessibility tree of the Firefox UI and responds to requests from screen readers. In content processes, the accessibility component creates accessibility trees from web content.

To respond to screen reader requests quickly, the accessibility tree from each content process is cached in the parent process.

Accessibility Trees

Accessibility trees can carry different kinds of information: informally, there are “local trees” that represent a document in the current process and “remote trees” that mirror a local tree created in a separate process.

A local tree can only contain nodes in the current process, i.e. you can visit any node in the tab document and its in-process iframes. However, out-of-process iframes appear as a separate local tree in a different process.

A remote tree, on the other hand, unifies these trees: you can visit any node in the tab document and both its in-process and out-of-process iframes.

This means there are multiple accessibility trees for a single tab: one local tree in the content process, one local tree for each out-of-process iframe, and one remote tree in the parent process that mirrors these local trees. The Firefox UI is represented by a single local tree in the parent process.

Tree Nodes

An accessibility tree is composed of nodes represented by the Accessible class and its subtypes. Below is an example local accessibility tree from example.com, as printed by a11y::logging::Tree (unfortunately, without type information):

A11Y TREE: Initial subtree; 44:14.388
  {
    : 0x107077a00; role: document, name: 'Example Domain', idx: 0, node: 0x105f84800, #document
      : 0x105fb8b30; role: heading, name: 'Example Domain', idx: 0, node: 0x107b048b0, h1
        : 0x105fb8c90; role: text leaf, name: 'Example Domain', idx: 0, node: 0x107b05600, #text
      : 0x105fb8d40; role: paragraph, idx: 1, node: 0x107b04940, p
        : 0x105fb8df0; role: text leaf, name: 'This domain is for use in illustrative examples in documents. You may use this domain in literature without prior coordination or asking for permission.', idx: 0, node: 0x107b05700, #text
      : 0x105fb8ea0; role: paragraph, idx: 2, node: 0x107b049d0, p
        : 0x107922030; role: link, name: 'More information...', idx: 0, node: 0x107b030e0, a [ href="https://www.iana.org/domains/example" ]
          : 0x1079220e0; role: text leaf, name: 'More information...', idx: 0, node: 0x107b05800, #text
  }

Accessible has a direct subtype for different kinds of accessibility trees: LocalAccessible for nodes of local trees and RemoteAccessibleBase for nodes of remote trees. For example, LocalAccessible can be used in content processes for web content and in the parent process for the Firefox UI. The descendants of these two types diverge.

LocalAccessible’s direct descendant is AccessibleWrap. By convention, a class that ends in Wrap is a platform-specific implementation so AccessibleWrap contains the platform-specific implementations of Accessible and LocalAccessible. AccessibleWrap's direct and indirect subtypes are representations of HTML and XUL nodes such as HTMLButtonAccessible and HTMLListBulletAccessible. The Document and the root node of the accessibility tree are also represented by the Accessible class: DocAccessible and DocAccessibleWrap as well as RootAccessible and RootAccessibleWrap extend AccessibleWrap.

RemoteAccessibleBase doesn’t have such an extensive type hierarchy. Its primary descendant is DocAccessibleParent which is the Document node of a remote tree located in the parent process: its local tree counterpart in a content process is DocAccessible.

Below is a graph that displays the same relationships described above. In the graph, solid lines represent direct descendants while dotted lines represent indirect descendants:

        flowchart TD
accTitle: Graph of the class hierarchy described above
Accessible --> LocalAccessible[LocalAccessible: local tree] & RemoteAccessibleBase[RemoteAccessibleBase: remote tree]
LocalAccessible --> AccessibleWrap[AccessibleWrap: platform-specific implementation]
AccessibleWrap -.-> DocAccessible & HTMLButtonAccessible & HTMLListBulletAccessible
DocAccessible --> DocAccessibleWrap --> RootAccessible --> RootAccessibleWrap
RemoteAccessibleBase -.-> DocAccessibleParent
    

Platform-Specific Behavior

Accessibility trees differ by platform. The platform-independent tree, composed of types like LocalAccessible and RemoteAccessibleBase, is marshalled into a platform-specific tree that makes it easier to implement the platform’s accessibility API. The platform tree is composed of the following node types: