はじめに
前回、Chrome が内部に持つ AX ツリー(アクセシビリティツリー)について書きました。
その中で「AX ツリーはプラットフォーム API への変換層を経て支援技術に渡る」と一言で流した部分があります。
この記事では、その変換層の正体である プラットフォームアクセシビリティ API(macOS の NSAccessibility、Windows の UIA / IA2 など)についてまとめます。
- スクリーンリーダーが実際に「会話している相手」は誰か
- macOS / Windows / Linux でそれぞれ何が使われているか
- 「NVDA では読めるのに Narrator では読めない」が構造的に起きる理由
- 実機テストで支援技術を複数使うべき理由
1. スクリーンリーダーは OS の API と会話している
スクリーンリーダーは、ブラウザと直接会話しているわけではありません。
OS・デスクトッププラットフォームで利用されるアクセシビリティ API を介して会話しています(Windows の IA2 のように OS 純正でないオープン標準も含まれるため、「OS の API」と言い切るより少し広い概念です)。
厳密には、NVDA のようにブラウザプロセス内で動くコードや仮想バッファを併用する支援技術もありますが、意味情報を取得する標準経路はこの API です。
この仕組みは Web に限ったものではありません。
ネイティブアプリも同じ API で UI 情報を公開しており、スクリーンリーダーから見れば「ブラウザも数あるアプリの一つ」です。
ブラウザは、Web ページの内容(AX ツリー)を OS ごとの API 形式に変換して公開する役割を担っています。
2. Core-AAM という仕様
「ARIA の各ロールを、各プラットフォーム API のどの型にマップするか」は、ブラウザが勝手に決めているわけではなく、W3C の Core-AAM(Core Accessibility API Mappings) が定義しています。
たとえば role="heading" の要素は、macOS では AXHeading、UIA では対応するコントロールタイプ、というように、API ごとのマッピング先が仕様の表として並んでいます。
HTML 要素固有のマッピング(<img> の alt の扱いなど)は HTML-AAM が受け持ちます。
前回の記事で扱ったアクセシブルネームの計算(AccName)と合わせると、仕様の分担はこう整理できます。
| 仕様 | 決めていること |
|---|---|
| WAI-ARIA | ロールや属性の意味 |
| AccName | アクセシブルネームの計算方法 |
| HTML-AAM | HTML 固有の要素・属性のマッピング(ロールのほか状態・プロパティも含む) |
| Core-AAM | ARIA のロール・状態・プロパティや、計算済みの名前・説明を各プラットフォーム API へどうマップするか |
3. macOS NSAccessibility
macOS のプラットフォーム API は、通称 macOS Accessibility API(AX API) と呼ばれる仕組みです。
UI 要素は AXRole / AXTitle / AXValue といった属性を持つオブジェクトとして外部から観測できます。
AppKit での現行実装はメソッドベースの NSAccessibilityProtocol が中心です(古いキー方式の NSAccessibility 非形式プロトコルは多くの用途で非推奨になっています)。
- 使う支援技術:VoiceOver(macOS 標準)
- Web の
headingはAXRole: AXHeadingにマップされる(見出しレベルはAXValueとして公開) - アクセシブルネームは基本的に
AXTitleとして公開される。説明(description)は名前とは別の情報として扱われ、由来や要素種別によって別の属性・関連で公開される
公式ドキュメント: Core-AAM 1.2 - aria-label のマッピング / Integrating accessibility into your app - Apple Developer
手元で覗くには、Xcode 付属の Accessibility Inspector が便利です。
画面上の要素をポイントすると、支援技術に公開されるのと同じアクセシビリティ階層と属性を観察できます(ただし VoiceOver の最終的な読み上げ挙動と完全に同一というわけではありません)。
Chrome の DevTools で見た AX ツリーと Accessibility Inspector の表示を突き合わせると、変換層で何が起きているかを具体的に確認できます。
4. Windows 2 系統あるのが歴史的ポイント
Windows は歴史的経緯で、アクセシビリティ API が複数並存しています。
| API | 登場時期 | 立ち位置 | 主な利用者 |
|---|---|---|---|
| MSAA | 1997 年 | 初代。情報量が少なく現在では力不足 | レガシー互換 |
| IA2(IAccessible2) | 2000年代半ば | MSAA を拡張したオープン標準。テキスト属性・リレーション等が豊富 | NVDA、JAWS(Chrome / Firefox の Web コンテンツで主要な経路) |
| UIA(UI Automation) | Windows Vista 世代に本格導入 | Microsoft 純正の後継 API。パターン / プロパティモデル | Narrator(Windows 標準)。NVDA も対象によって利用 |
IA2 ブラウザとスクリーンリーダー陣営が作ったオープン標準
MSAA だけではリッチテキストの属性や要素間のリレーションなど、Web ページの表現に必要な情報が足りませんでした。
それを補うために生まれたのが IAccessible2(IA2)です。
IBM が開発し、現在は Linux Foundation 管理のオープン標準になっています。
Chrome や Firefox は長らくこちらを主経路とし、NVDA や JAWS もこれを読む構成が定番でした。
UIA Microsoft の公式路線
UI Automation(UIA)は Microsoft が MSAA の後継として設計した API で、Windows 標準のスクリーンリーダーである Narrator はこちらを使います。
Chrome の UIA サポートは段階的に拡充されてきていますが、機能フラグでの有効化を含むまだ発展途上の経路で、Web コンテンツの主経路は現時点では IA2 のままです。
「NVDA と Narrator で結果が違う」が構造的に起きる
ここが実務上いちばん重要なポイントです。
Narrator は主に UIA 経路、NVDA は Chromium 系ブラウザの Web コンテンツでは現在も IA2 が主要な経路と、同じ Chrome を読んでいても通っている API が違うため、片方では読み上げられる情報がもう片方では欠ける、という現象が構造的に起こりえます。
なお NVDA 自体は IA2 と UIA の両方を実装しており、ブラウザの UIA 対応状況・NVDA の設定・対象 UI によっては UIA 経路も使われます。
「NVDA = IA2」という一対一対応ではない点は押さえておいてください。
手元で覗くには、Microsoft の Accessibility Insights for Windows(UIA ベース)が使えます。
IA2 側の確認には、NVDA 自体のオブジェクトナビゲーション機能も役立ちます。
5. Linux AT-SPI2
Linux デスクトップには AT-SPI2 という第 3 の系統があります。
D-Bus ベースの基盤で、GNOME の Orca スクリーンリーダーがこれを使います。
主要プラットフォームだけで 3 系統の API があり、ブラウザはそのすべてへの変換を実装している、ということです。
6. 実務への示唆
「AX ツリーで正しい」の先にもう 1 つ変換がある
DevTools や CDP で AX ツリーを確認して正しくても、その先の Core-AAM マッピングや API の表現力の差で、情報が落ちたり形を変えたりする層がもう 1 枚あります。
AX ツリーの確認は「ブラウザまでは正しい」ことの確認であって、ユーザーに届くまでの全経路の保証ではありません。
支援技術の選択 = API の選択
NVDA で Chromium 系ブラウザをテストすることは主に IA2 経路をテストすること(設定・対象により UIA も)、Narrator なら UIA 経路、VoiceOver なら macOS AX API 経路のテストです。
「実機テストでは複数の支援技術を使いましょう」とよく言われるのは、単にソフトの癖の違いだけでなく、通る API 自体が違うからです。
テスト構成の目安
| 環境 | 支援技術 | 通る API |
|---|---|---|
| macOS | VoiceOver | macOS AX API(NSAccessibility 系) |
| Windows | NVDA | 主に IA2(設定・対象により UIA も) |
| Windows | Narrator | UIA |
この 3 構成は、デスクトップの代表的な API 経路を比較するための最小構成です。
Safari + VoiceOver の組み合わせや JAWS、モバイルの VoiceOver / TalkBack まではカバーしていない点には注意してください。
まとめ
- スクリーンリーダーはブラウザと直接会話せず、OS・プラットフォームのアクセシビリティ API を介している
- 変換ルールは W3C の Core-AAM / HTML-AAM が定義している
- macOS は AX API(NSAccessibility 系)、Windows は IA2 と UIA の 2 系統、Linux は AT-SPI2
- NVDA(主に IA2)と Narrator(UIA)では通る API が違うため、結果の食い違いは構造的に起きうる
- AX ツリーの確認だけでなく、実機の支援技術での確認が必要な理由はこの変換層にある
ARIA を書くとき、その情報がどんな経路でユーザーに届くのかを一段深く知っておくと、「なぜこの支援技術では読めないのか」を調査するときの見通しがよくなるはずです。
認識が間違っている箇所があれば、コメントで教えていただけると嬉しいです。
参考リンク
- Core Accessibility API Mappings 1.2
- HTML Accessibility API Mappings 1.0
- NSAccessibilityProtocol - Apple Developer Documentation
- Integrating accessibility into your app - Apple Developer
- IAccessible2 - Linux Foundation
- UI Automation - Microsoft Learn
- NVDA Technical Design Overview
- Accessibility Insights
- AT-SPI2 - freedesktop.org