1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/accessibility/accessibility_tree_formatter_utils_win.h"
6
7#include <oleacc.h>
8
9#include <map>
10#include <string>
11
12#include "base/memory/singleton.h"
13#include "base/strings/string_util.h"
14#include "third_party/iaccessible2/ia2_api_all.h"
15
16namespace content {
17namespace {
18
19class AccessibilityRoleStateMap {
20 public:
21  static AccessibilityRoleStateMap* GetInstance();
22
23  std::map<int32, base::string16> ia_role_string_map;
24  std::map<int32, base::string16> ia2_role_string_map;
25  std::map<int32, base::string16> ia_state_string_map;
26  std::map<int32, base::string16> ia2_state_string_map;
27
28 private:
29  AccessibilityRoleStateMap();
30  virtual ~AccessibilityRoleStateMap() {}
31
32  friend struct DefaultSingletonTraits<AccessibilityRoleStateMap>;
33
34  DISALLOW_COPY_AND_ASSIGN(AccessibilityRoleStateMap);
35};
36
37// static
38AccessibilityRoleStateMap* AccessibilityRoleStateMap::GetInstance() {
39  return Singleton<AccessibilityRoleStateMap,
40                   LeakySingletonTraits<AccessibilityRoleStateMap> >::get();
41}
42
43AccessibilityRoleStateMap::AccessibilityRoleStateMap() {
44// Convenience macros for generating readable strings.
45#define IA_ROLE_MAP(x) ia_role_string_map[x] = L###x;  \
46                       ia2_role_string_map[x] = L###x;
47#define IA2_ROLE_MAP(x) ia2_role_string_map[x] = L###x;
48#define IA_STATE_MAP(x) ia_state_string_map[STATE_SYSTEM_##x] = L###x;
49#define IA2_STATE_MAP(x) ia2_state_string_map[x] = L###x;
50
51  // MSAA / IAccessible roles. Each one of these is also a valid
52  // IAccessible2 role, the IA_ROLE_MAP macro adds it to both.
53  IA_ROLE_MAP(ROLE_SYSTEM_ALERT)
54  IA_ROLE_MAP(ROLE_SYSTEM_ANIMATION)
55  IA_ROLE_MAP(ROLE_SYSTEM_APPLICATION)
56  IA_ROLE_MAP(ROLE_SYSTEM_BORDER)
57  IA_ROLE_MAP(ROLE_SYSTEM_BUTTONDROPDOWN)
58  IA_ROLE_MAP(ROLE_SYSTEM_BUTTONDROPDOWNGRID)
59  IA_ROLE_MAP(ROLE_SYSTEM_BUTTONMENU)
60  IA_ROLE_MAP(ROLE_SYSTEM_CARET)
61  IA_ROLE_MAP(ROLE_SYSTEM_CELL)
62  IA_ROLE_MAP(ROLE_SYSTEM_CHARACTER)
63  IA_ROLE_MAP(ROLE_SYSTEM_CHART)
64  IA_ROLE_MAP(ROLE_SYSTEM_CHECKBUTTON)
65  IA_ROLE_MAP(ROLE_SYSTEM_CLIENT)
66  IA_ROLE_MAP(ROLE_SYSTEM_CLOCK)
67  IA_ROLE_MAP(ROLE_SYSTEM_COLUMN)
68  IA_ROLE_MAP(ROLE_SYSTEM_COLUMNHEADER)
69  IA_ROLE_MAP(ROLE_SYSTEM_COMBOBOX)
70  IA_ROLE_MAP(ROLE_SYSTEM_CURSOR)
71  IA_ROLE_MAP(ROLE_SYSTEM_DIAGRAM)
72  IA_ROLE_MAP(ROLE_SYSTEM_DIAL)
73  IA_ROLE_MAP(ROLE_SYSTEM_DIALOG)
74  IA_ROLE_MAP(ROLE_SYSTEM_DOCUMENT)
75  IA_ROLE_MAP(ROLE_SYSTEM_DROPLIST)
76  IA_ROLE_MAP(ROLE_SYSTEM_EQUATION)
77  IA_ROLE_MAP(ROLE_SYSTEM_GRAPHIC)
78  IA_ROLE_MAP(ROLE_SYSTEM_GRIP)
79  IA_ROLE_MAP(ROLE_SYSTEM_GROUPING)
80  IA_ROLE_MAP(ROLE_SYSTEM_HELPBALLOON)
81  IA_ROLE_MAP(ROLE_SYSTEM_HOTKEYFIELD)
82  IA_ROLE_MAP(ROLE_SYSTEM_INDICATOR)
83  IA_ROLE_MAP(ROLE_SYSTEM_IPADDRESS)
84  IA_ROLE_MAP(ROLE_SYSTEM_LINK)
85  IA_ROLE_MAP(ROLE_SYSTEM_LIST)
86  IA_ROLE_MAP(ROLE_SYSTEM_LISTITEM)
87  IA_ROLE_MAP(ROLE_SYSTEM_MENUBAR)
88  IA_ROLE_MAP(ROLE_SYSTEM_MENUITEM)
89  IA_ROLE_MAP(ROLE_SYSTEM_MENUPOPUP)
90  IA_ROLE_MAP(ROLE_SYSTEM_OUTLINE)
91  IA_ROLE_MAP(ROLE_SYSTEM_OUTLINEBUTTON)
92  IA_ROLE_MAP(ROLE_SYSTEM_OUTLINEITEM)
93  IA_ROLE_MAP(ROLE_SYSTEM_PAGETAB)
94  IA_ROLE_MAP(ROLE_SYSTEM_PAGETABLIST)
95  IA_ROLE_MAP(ROLE_SYSTEM_PANE)
96  IA_ROLE_MAP(ROLE_SYSTEM_PROGRESSBAR)
97  IA_ROLE_MAP(ROLE_SYSTEM_PROPERTYPAGE)
98  IA_ROLE_MAP(ROLE_SYSTEM_PUSHBUTTON)
99  IA_ROLE_MAP(ROLE_SYSTEM_RADIOBUTTON)
100  IA_ROLE_MAP(ROLE_SYSTEM_ROW)
101  IA_ROLE_MAP(ROLE_SYSTEM_ROWHEADER)
102  IA_ROLE_MAP(ROLE_SYSTEM_SCROLLBAR)
103  IA_ROLE_MAP(ROLE_SYSTEM_SEPARATOR)
104  IA_ROLE_MAP(ROLE_SYSTEM_SLIDER)
105  IA_ROLE_MAP(ROLE_SYSTEM_SOUND)
106  IA_ROLE_MAP(ROLE_SYSTEM_SPINBUTTON)
107  IA_ROLE_MAP(ROLE_SYSTEM_SPLITBUTTON)
108  IA_ROLE_MAP(ROLE_SYSTEM_STATICTEXT)
109  IA_ROLE_MAP(ROLE_SYSTEM_STATUSBAR)
110  IA_ROLE_MAP(ROLE_SYSTEM_TABLE)
111  IA_ROLE_MAP(ROLE_SYSTEM_TEXT)
112  IA_ROLE_MAP(ROLE_SYSTEM_TITLEBAR)
113  IA_ROLE_MAP(ROLE_SYSTEM_TOOLBAR)
114  IA_ROLE_MAP(ROLE_SYSTEM_TOOLTIP)
115  IA_ROLE_MAP(ROLE_SYSTEM_WHITESPACE)
116  IA_ROLE_MAP(ROLE_SYSTEM_WINDOW)
117
118  // IAccessible2 roles.
119  IA2_ROLE_MAP(IA2_ROLE_CANVAS)
120  IA2_ROLE_MAP(IA2_ROLE_CAPTION)
121  IA2_ROLE_MAP(IA2_ROLE_CHECK_MENU_ITEM)
122  IA2_ROLE_MAP(IA2_ROLE_COLOR_CHOOSER)
123  IA2_ROLE_MAP(IA2_ROLE_DATE_EDITOR)
124  IA2_ROLE_MAP(IA2_ROLE_DESKTOP_ICON)
125  IA2_ROLE_MAP(IA2_ROLE_DESKTOP_PANE)
126  IA2_ROLE_MAP(IA2_ROLE_DIRECTORY_PANE)
127  IA2_ROLE_MAP(IA2_ROLE_EDITBAR)
128  IA2_ROLE_MAP(IA2_ROLE_EMBEDDED_OBJECT)
129  IA2_ROLE_MAP(IA2_ROLE_ENDNOTE)
130  IA2_ROLE_MAP(IA2_ROLE_FILE_CHOOSER)
131  IA2_ROLE_MAP(IA2_ROLE_FONT_CHOOSER)
132  IA2_ROLE_MAP(IA2_ROLE_FOOTER)
133  IA2_ROLE_MAP(IA2_ROLE_FOOTNOTE)
134  IA2_ROLE_MAP(IA2_ROLE_FORM)
135  IA2_ROLE_MAP(IA2_ROLE_FRAME)
136  IA2_ROLE_MAP(IA2_ROLE_GLASS_PANE)
137  IA2_ROLE_MAP(IA2_ROLE_HEADER)
138  IA2_ROLE_MAP(IA2_ROLE_HEADING)
139  IA2_ROLE_MAP(IA2_ROLE_ICON)
140  IA2_ROLE_MAP(IA2_ROLE_IMAGE_MAP)
141  IA2_ROLE_MAP(IA2_ROLE_INPUT_METHOD_WINDOW)
142  IA2_ROLE_MAP(IA2_ROLE_INTERNAL_FRAME)
143  IA2_ROLE_MAP(IA2_ROLE_LABEL)
144  IA2_ROLE_MAP(IA2_ROLE_LAYERED_PANE)
145  IA2_ROLE_MAP(IA2_ROLE_NOTE)
146  IA2_ROLE_MAP(IA2_ROLE_OPTION_PANE)
147  IA2_ROLE_MAP(IA2_ROLE_PAGE)
148  IA2_ROLE_MAP(IA2_ROLE_PARAGRAPH)
149  IA2_ROLE_MAP(IA2_ROLE_RADIO_MENU_ITEM)
150  IA2_ROLE_MAP(IA2_ROLE_REDUNDANT_OBJECT)
151  IA2_ROLE_MAP(IA2_ROLE_ROOT_PANE)
152  IA2_ROLE_MAP(IA2_ROLE_RULER)
153  IA2_ROLE_MAP(IA2_ROLE_SCROLL_PANE)
154  IA2_ROLE_MAP(IA2_ROLE_SECTION)
155  IA2_ROLE_MAP(IA2_ROLE_SHAPE)
156  IA2_ROLE_MAP(IA2_ROLE_SPLIT_PANE)
157  IA2_ROLE_MAP(IA2_ROLE_TEAR_OFF_MENU)
158  IA2_ROLE_MAP(IA2_ROLE_TERMINAL)
159  IA2_ROLE_MAP(IA2_ROLE_TEXT_FRAME)
160  IA2_ROLE_MAP(IA2_ROLE_TOGGLE_BUTTON)
161  IA2_ROLE_MAP(IA2_ROLE_UNKNOWN)
162  IA2_ROLE_MAP(IA2_ROLE_VIEW_PORT)
163
164  // MSAA / IAccessible states. Unlike roles, these are not also IA2 states.
165  IA_STATE_MAP(ALERT_HIGH)
166  IA_STATE_MAP(ALERT_LOW)
167  IA_STATE_MAP(ALERT_MEDIUM)
168  IA_STATE_MAP(ANIMATED)
169  IA_STATE_MAP(BUSY)
170  IA_STATE_MAP(CHECKED)
171  IA_STATE_MAP(COLLAPSED)
172  IA_STATE_MAP(DEFAULT)
173  IA_STATE_MAP(EXPANDED)
174  IA_STATE_MAP(EXTSELECTABLE)
175  IA_STATE_MAP(FLOATING)
176  IA_STATE_MAP(FOCUSABLE)
177  IA_STATE_MAP(FOCUSED)
178  IA_STATE_MAP(HASPOPUP)
179  IA_STATE_MAP(HOTTRACKED)
180  IA_STATE_MAP(INVISIBLE)
181  IA_STATE_MAP(LINKED)
182  IA_STATE_MAP(MARQUEED)
183  IA_STATE_MAP(MIXED)
184  IA_STATE_MAP(MOVEABLE)
185  IA_STATE_MAP(MULTISELECTABLE)
186  IA_STATE_MAP(OFFSCREEN)
187  IA_STATE_MAP(PRESSED)
188  IA_STATE_MAP(PROTECTED)
189  IA_STATE_MAP(READONLY)
190  IA_STATE_MAP(SELECTABLE)
191  IA_STATE_MAP(SELECTED)
192  IA_STATE_MAP(SELFVOICING)
193  IA_STATE_MAP(SIZEABLE)
194  IA_STATE_MAP(TRAVERSED)
195  IA_STATE_MAP(UNAVAILABLE)
196
197  // IAccessible2 states.
198  IA2_STATE_MAP(IA2_STATE_ACTIVE)
199  IA2_STATE_MAP(IA2_STATE_ARMED)
200  IA2_STATE_MAP(IA2_STATE_DEFUNCT)
201  IA2_STATE_MAP(IA2_STATE_EDITABLE)
202  IA2_STATE_MAP(IA2_STATE_ICONIFIED)
203  IA2_STATE_MAP(IA2_STATE_INVALID_ENTRY)
204  IA2_STATE_MAP(IA2_STATE_MANAGES_DESCENDANTS)
205  IA2_STATE_MAP(IA2_STATE_MODAL)
206  IA2_STATE_MAP(IA2_STATE_MULTI_LINE)
207  IA2_STATE_MAP(IA2_STATE_REQUIRED)
208  IA2_STATE_MAP(IA2_STATE_SELECTABLE_TEXT)
209  IA2_STATE_MAP(IA2_STATE_SINGLE_LINE)
210  IA2_STATE_MAP(IA2_STATE_STALE)
211  IA2_STATE_MAP(IA2_STATE_SUPPORTS_AUTOCOMPLETION)
212  IA2_STATE_MAP(IA2_STATE_TRANSIENT)
213
214  // Untested states include those that would be repeated on nearly every node,
215  // or would vary based on window size.
216  // IA2_STATE_MAP(IA2_STATE_HORIZONTAL) // Untested.
217  // IA2_STATE_MAP(IA2_STATE_OPAQUE) // Untested.
218  // IA2_STATE_MAP(IA2_STATE_VERTICAL) // Untested.
219}
220
221}  // namespace.
222
223base::string16 IAccessibleRoleToString(int32 ia_role) {
224  return AccessibilityRoleStateMap::GetInstance()->ia_role_string_map[ia_role];
225}
226
227base::string16 IAccessible2RoleToString(int32 ia_role) {
228  return AccessibilityRoleStateMap::GetInstance()->ia2_role_string_map[ia_role];
229}
230
231void IAccessibleStateToStringVector(int32 ia_state,
232                                    std::vector<base::string16>* result) {
233  const std::map<int32, base::string16>& state_string_map =
234      AccessibilityRoleStateMap::GetInstance()->ia_state_string_map;
235  std::map<int32, base::string16>::const_iterator it;
236  for (it = state_string_map.begin(); it != state_string_map.end(); ++it) {
237    if (it->first & ia_state)
238      result->push_back(it->second);
239  }
240}
241
242base::string16 IAccessibleStateToString(int32 ia_state) {
243  std::vector<base::string16> strings;
244  IAccessibleStateToStringVector(ia_state, &strings);
245  return JoinString(strings, ',');
246}
247
248void IAccessible2StateToStringVector(int32 ia2_state,
249                                     std::vector<base::string16>* result) {
250  const std::map<int32, base::string16>& state_string_map =
251      AccessibilityRoleStateMap::GetInstance()->ia2_state_string_map;
252  std::map<int32, base::string16>::const_iterator it;
253  for (it = state_string_map.begin(); it != state_string_map.end(); ++it) {
254    if (it->first & ia2_state)
255      result->push_back(it->second);
256  }
257}
258
259base::string16 IAccessible2StateToString(int32 ia2_state) {
260  std::vector<base::string16> strings;
261  IAccessible2StateToStringVector(ia2_state, &strings);
262  return JoinString(strings, ',');
263}
264
265}  // namespace content
266