Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(572)

Side by Side Diff: content/browser/accessibility/browser_accessibility_cocoa.mm

Issue 420653003: MacViews: Accessibility bridge (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 2nd draft, based on 423513005 Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | ui/accessibility/accessibility.gyp » ('j') | ui/accessibility/accessibility.gyp » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <execinfo.h> 5 #include <execinfo.h>
6 6
7 #import "content/browser/accessibility/browser_accessibility_cocoa.h" 7 #import "content/browser/accessibility/browser_accessibility_cocoa.h"
8 8
9 #include <map> 9 #include <map>
10 10
11 #include "base/basictypes.h" 11 #include "base/basictypes.h"
12 #include "base/strings/string16.h" 12 #include "base/strings/string16.h"
13 #include "base/strings/sys_string_conversions.h" 13 #include "base/strings/sys_string_conversions.h"
14 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
15 #include "content/browser/accessibility/browser_accessibility_manager.h" 15 #include "content/browser/accessibility/browser_accessibility_manager.h"
16 #include "content/browser/accessibility/browser_accessibility_manager_mac.h" 16 #include "content/browser/accessibility/browser_accessibility_manager_mac.h"
17 #include "content/public/common/content_client.h" 17 #include "content/public/common/content_client.h"
18 #include "grit/webkit_strings.h" 18 #include "grit/webkit_strings.h"
19 #import "ui/accessibility/platform/ax_platform_node_mac.h"
19 20
20 // See http://openradar.appspot.com/9896491. This SPI has been tested on 10.5, 21 // See http://openradar.appspot.com/9896491. This SPI has been tested on 10.5,
21 // 10.6, and 10.7. It allows accessibility clients to observe events posted on 22 // 10.6, and 10.7. It allows accessibility clients to observe events posted on
22 // this object. 23 // this object.
23 extern "C" void NSAccessibilityUnregisterUniqueIdForUIElement(id element); 24 extern "C" void NSAccessibilityUnregisterUniqueIdForUIElement(id element);
24 25
25 using ui::AXNodeData; 26 using ui::AXNodeData;
26 using content::BrowserAccessibility; 27 using content::BrowserAccessibility;
27 using content::BrowserAccessibilityManager; 28 using content::BrowserAccessibilityManager;
28 using content::BrowserAccessibilityManagerMac; 29 using content::BrowserAccessibilityManagerMac;
29 using content::ContentClient; 30 using content::ContentClient;
30 typedef ui::AXStringAttribute StringAttribute; 31 typedef ui::AXStringAttribute StringAttribute;
31 32
32 namespace { 33 namespace {
33 34
34 // Returns an autoreleased copy of the AXNodeData's attribute. 35 // Returns an autoreleased copy of the AXNodeData's attribute.
35 NSString* NSStringForStringAttribute( 36 NSString* NSStringForStringAttribute(
36 BrowserAccessibility* browserAccessibility, 37 BrowserAccessibility* browserAccessibility,
37 StringAttribute attribute) { 38 StringAttribute attribute) {
38 return base::SysUTF8ToNSString( 39 return base::SysUTF8ToNSString(
39 browserAccessibility->GetStringAttribute(attribute)); 40 browserAccessibility->GetStringAttribute(attribute));
40 } 41 }
41 42
42 struct MapEntry {
43 ui::AXRole webKitValue;
44 NSString* nativeValue;
45 };
46
47 typedef std::map<ui::AXRole, NSString*> RoleMap;
48
49 // GetState checks the bitmask used in AXNodeData to check 43 // GetState checks the bitmask used in AXNodeData to check
50 // if the given state was set on the accessibility object. 44 // if the given state was set on the accessibility object.
51 bool GetState(BrowserAccessibility* accessibility, ui::AXState state) { 45 bool GetState(BrowserAccessibility* accessibility, ui::AXState state) {
52 return ((accessibility->GetState() >> state) & 1); 46 return ((accessibility->GetState() >> state) & 1);
53 } 47 }
54 48
55 RoleMap BuildRoleMap() {
56 const MapEntry roles[] = {
57 { ui::AX_ROLE_ALERT, NSAccessibilityGroupRole },
58 { ui::AX_ROLE_ALERT_DIALOG, NSAccessibilityGroupRole },
59 { ui::AX_ROLE_ANNOTATION, NSAccessibilityUnknownRole },
60 { ui::AX_ROLE_APPLICATION, NSAccessibilityGroupRole },
61 { ui::AX_ROLE_ARTICLE, NSAccessibilityGroupRole },
62 { ui::AX_ROLE_BANNER, NSAccessibilityGroupRole },
63 { ui::AX_ROLE_BROWSER, NSAccessibilityBrowserRole },
64 { ui::AX_ROLE_BUSY_INDICATOR, NSAccessibilityBusyIndicatorRole },
65 { ui::AX_ROLE_BUTTON, NSAccessibilityButtonRole },
66 { ui::AX_ROLE_CANVAS, NSAccessibilityImageRole },
67 { ui::AX_ROLE_CELL, @"AXCell" },
68 { ui::AX_ROLE_CHECK_BOX, NSAccessibilityCheckBoxRole },
69 { ui::AX_ROLE_COLOR_WELL, NSAccessibilityColorWellRole },
70 { ui::AX_ROLE_COLUMN, NSAccessibilityColumnRole },
71 { ui::AX_ROLE_COLUMN_HEADER, @"AXCell" },
72 { ui::AX_ROLE_COMBO_BOX, NSAccessibilityComboBoxRole },
73 { ui::AX_ROLE_COMPLEMENTARY, NSAccessibilityGroupRole },
74 { ui::AX_ROLE_CONTENT_INFO, NSAccessibilityGroupRole },
75 { ui::AX_ROLE_DEFINITION, NSAccessibilityGroupRole },
76 { ui::AX_ROLE_DESCRIPTION_LIST_DETAIL, NSAccessibilityGroupRole },
77 { ui::AX_ROLE_DESCRIPTION_LIST_TERM, NSAccessibilityGroupRole },
78 { ui::AX_ROLE_DIALOG, NSAccessibilityGroupRole },
79 { ui::AX_ROLE_DIRECTORY, NSAccessibilityListRole },
80 { ui::AX_ROLE_DISCLOSURE_TRIANGLE, NSAccessibilityDisclosureTriangleRole },
81 { ui::AX_ROLE_DIV, NSAccessibilityGroupRole },
82 { ui::AX_ROLE_DOCUMENT, NSAccessibilityGroupRole },
83 { ui::AX_ROLE_DRAWER, NSAccessibilityDrawerRole },
84 { ui::AX_ROLE_EDITABLE_TEXT, NSAccessibilityTextFieldRole },
85 { ui::AX_ROLE_FOOTER, NSAccessibilityGroupRole },
86 { ui::AX_ROLE_FORM, NSAccessibilityGroupRole },
87 { ui::AX_ROLE_GRID, NSAccessibilityGridRole },
88 { ui::AX_ROLE_GROUP, NSAccessibilityGroupRole },
89 { ui::AX_ROLE_GROW_AREA, NSAccessibilityGrowAreaRole },
90 { ui::AX_ROLE_HEADING, @"AXHeading" },
91 { ui::AX_ROLE_HELP_TAG, NSAccessibilityHelpTagRole },
92 { ui::AX_ROLE_HORIZONTAL_RULE, NSAccessibilityGroupRole },
93 { ui::AX_ROLE_IFRAME, NSAccessibilityGroupRole },
94 { ui::AX_ROLE_IGNORED, NSAccessibilityUnknownRole },
95 { ui::AX_ROLE_IMAGE, NSAccessibilityImageRole },
96 { ui::AX_ROLE_IMAGE_MAP, NSAccessibilityGroupRole },
97 { ui::AX_ROLE_IMAGE_MAP_LINK, NSAccessibilityLinkRole },
98 { ui::AX_ROLE_INCREMENTOR, NSAccessibilityIncrementorRole },
99 { ui::AX_ROLE_LABEL_TEXT, NSAccessibilityGroupRole },
100 { ui::AX_ROLE_LINK, NSAccessibilityLinkRole },
101 { ui::AX_ROLE_LIST, NSAccessibilityListRole },
102 { ui::AX_ROLE_LIST_BOX, NSAccessibilityListRole },
103 { ui::AX_ROLE_LIST_BOX_OPTION, NSAccessibilityStaticTextRole },
104 { ui::AX_ROLE_LIST_ITEM, NSAccessibilityGroupRole },
105 { ui::AX_ROLE_LIST_MARKER, @"AXListMarker" },
106 { ui::AX_ROLE_LOG, NSAccessibilityGroupRole },
107 { ui::AX_ROLE_MAIN, NSAccessibilityGroupRole },
108 { ui::AX_ROLE_MARQUEE, NSAccessibilityGroupRole },
109 { ui::AX_ROLE_MATH, NSAccessibilityGroupRole },
110 { ui::AX_ROLE_MATTE, NSAccessibilityMatteRole },
111 { ui::AX_ROLE_MENU, NSAccessibilityMenuRole },
112 { ui::AX_ROLE_MENU_BAR, NSAccessibilityMenuBarRole },
113 { ui::AX_ROLE_MENU_BUTTON, NSAccessibilityButtonRole },
114 { ui::AX_ROLE_MENU_ITEM, NSAccessibilityMenuItemRole },
115 { ui::AX_ROLE_MENU_LIST_OPTION, NSAccessibilityMenuItemRole },
116 { ui::AX_ROLE_MENU_LIST_POPUP, NSAccessibilityUnknownRole },
117 { ui::AX_ROLE_NAVIGATION, NSAccessibilityGroupRole },
118 { ui::AX_ROLE_NOTE, NSAccessibilityGroupRole },
119 { ui::AX_ROLE_OUTLINE, NSAccessibilityOutlineRole },
120 { ui::AX_ROLE_PARAGRAPH, NSAccessibilityGroupRole },
121 { ui::AX_ROLE_POP_UP_BUTTON, NSAccessibilityPopUpButtonRole },
122 { ui::AX_ROLE_PRESENTATIONAL, NSAccessibilityGroupRole },
123 { ui::AX_ROLE_PROGRESS_INDICATOR, NSAccessibilityProgressIndicatorRole },
124 { ui::AX_ROLE_RADIO_BUTTON, NSAccessibilityRadioButtonRole },
125 { ui::AX_ROLE_RADIO_GROUP, NSAccessibilityRadioGroupRole },
126 { ui::AX_ROLE_REGION, NSAccessibilityGroupRole },
127 { ui::AX_ROLE_ROOT_WEB_AREA, @"AXWebArea" },
128 { ui::AX_ROLE_ROW, NSAccessibilityRowRole },
129 { ui::AX_ROLE_ROW_HEADER, @"AXCell" },
130 { ui::AX_ROLE_RULER, NSAccessibilityRulerRole },
131 { ui::AX_ROLE_RULER_MARKER, NSAccessibilityRulerMarkerRole },
132 { ui::AX_ROLE_SCROLL_BAR, NSAccessibilityScrollBarRole },
133 { ui::AX_ROLE_SEARCH, NSAccessibilityGroupRole },
134 { ui::AX_ROLE_SHEET, NSAccessibilitySheetRole },
135 { ui::AX_ROLE_SLIDER, NSAccessibilitySliderRole },
136 { ui::AX_ROLE_SLIDER_THUMB, NSAccessibilityValueIndicatorRole },
137 { ui::AX_ROLE_SPIN_BUTTON, NSAccessibilitySliderRole },
138 { ui::AX_ROLE_SPLITTER, NSAccessibilitySplitterRole },
139 { ui::AX_ROLE_SPLIT_GROUP, NSAccessibilitySplitGroupRole },
140 { ui::AX_ROLE_STATIC_TEXT, NSAccessibilityStaticTextRole },
141 { ui::AX_ROLE_STATUS, NSAccessibilityGroupRole },
142 { ui::AX_ROLE_SVG_ROOT, NSAccessibilityGroupRole },
143 { ui::AX_ROLE_SYSTEM_WIDE, NSAccessibilityUnknownRole },
144 { ui::AX_ROLE_TAB, NSAccessibilityRadioButtonRole },
145 { ui::AX_ROLE_TABLE, NSAccessibilityTableRole },
146 { ui::AX_ROLE_TABLE_HEADER_CONTAINER, NSAccessibilityGroupRole },
147 { ui::AX_ROLE_TAB_LIST, NSAccessibilityTabGroupRole },
148 { ui::AX_ROLE_TAB_PANEL, NSAccessibilityGroupRole },
149 { ui::AX_ROLE_TEXT_AREA, NSAccessibilityTextAreaRole },
150 { ui::AX_ROLE_TEXT_FIELD, NSAccessibilityTextFieldRole },
151 { ui::AX_ROLE_TIMER, NSAccessibilityGroupRole },
152 { ui::AX_ROLE_TOGGLE_BUTTON, NSAccessibilityCheckBoxRole },
153 { ui::AX_ROLE_TOOLBAR, NSAccessibilityToolbarRole },
154 { ui::AX_ROLE_TOOLTIP, NSAccessibilityGroupRole },
155 { ui::AX_ROLE_TREE, NSAccessibilityOutlineRole },
156 { ui::AX_ROLE_TREE_GRID, NSAccessibilityTableRole },
157 { ui::AX_ROLE_TREE_ITEM, NSAccessibilityRowRole },
158 { ui::AX_ROLE_VALUE_INDICATOR, NSAccessibilityValueIndicatorRole },
159 { ui::AX_ROLE_WEB_AREA, @"AXWebArea" },
160 { ui::AX_ROLE_WINDOW, NSAccessibilityWindowRole },
161
162 // TODO(dtseng): we don't correctly support the attributes for these roles.
163 // { ui::AX_ROLE_SCROLL_AREA, NSAccessibilityScrollAreaRole },
164 };
165
166 RoleMap role_map;
167 for (size_t i = 0; i < arraysize(roles); ++i)
168 role_map[roles[i].webKitValue] = roles[i].nativeValue;
169 return role_map;
170 }
171
172 // A mapping of webkit roles to native roles.
173 NSString* NativeRoleFromAXRole(
174 const ui::AXRole& role) {
175 CR_DEFINE_STATIC_LOCAL(RoleMap, web_accessibility_to_native_role,
176 (BuildRoleMap()));
177 RoleMap::iterator it = web_accessibility_to_native_role.find(role);
178 if (it != web_accessibility_to_native_role.end())
179 return it->second;
180 else
181 return NSAccessibilityUnknownRole;
182 }
183
184 RoleMap BuildSubroleMap() {
185 const MapEntry subroles[] = {
186 { ui::AX_ROLE_ALERT, @"AXApplicationAlert" },
187 { ui::AX_ROLE_ALERT_DIALOG, @"AXApplicationAlertDialog" },
188 { ui::AX_ROLE_ARTICLE, @"AXDocumentArticle" },
189 { ui::AX_ROLE_DEFINITION, @"AXDefinition" },
190 { ui::AX_ROLE_DESCRIPTION_LIST_DETAIL, @"AXDescription" },
191 { ui::AX_ROLE_DESCRIPTION_LIST_TERM, @"AXTerm" },
192 { ui::AX_ROLE_DIALOG, @"AXApplicationDialog" },
193 { ui::AX_ROLE_DOCUMENT, @"AXDocument" },
194 { ui::AX_ROLE_FOOTER, @"AXLandmarkContentInfo" },
195 { ui::AX_ROLE_APPLICATION, @"AXLandmarkApplication" },
196 { ui::AX_ROLE_BANNER, @"AXLandmarkBanner" },
197 { ui::AX_ROLE_COMPLEMENTARY, @"AXLandmarkComplementary" },
198 { ui::AX_ROLE_CONTENT_INFO, @"AXLandmarkContentInfo" },
199 { ui::AX_ROLE_MAIN, @"AXLandmarkMain" },
200 { ui::AX_ROLE_NAVIGATION, @"AXLandmarkNavigation" },
201 { ui::AX_ROLE_SEARCH, @"AXLandmarkSearch" },
202 { ui::AX_ROLE_LOG, @"AXApplicationLog" },
203 { ui::AX_ROLE_MARQUEE, @"AXApplicationMarquee" },
204 { ui::AX_ROLE_MATH, @"AXDocumentMath" },
205 { ui::AX_ROLE_NOTE, @"AXDocumentNote" },
206 { ui::AX_ROLE_REGION, @"AXDocumentRegion" },
207 { ui::AX_ROLE_STATUS, @"AXApplicationStatus" },
208 { ui::AX_ROLE_TAB_PANEL, @"AXTabPanel" },
209 { ui::AX_ROLE_TIMER, @"AXApplicationTimer" },
210 { ui::AX_ROLE_TOGGLE_BUTTON, @"AXToggleButton" },
211 { ui::AX_ROLE_TOOLTIP, @"AXUserInterfaceTooltip" },
212 { ui::AX_ROLE_TREE_ITEM, NSAccessibilityOutlineRowSubrole },
213 };
214
215 RoleMap subrole_map;
216 for (size_t i = 0; i < arraysize(subroles); ++i)
217 subrole_map[subroles[i].webKitValue] = subroles[i].nativeValue;
218 return subrole_map;
219 }
220
221 // A mapping of webkit roles to native subroles.
222 NSString* NativeSubroleFromAXRole(
223 const ui::AXRole& role) {
224 CR_DEFINE_STATIC_LOCAL(RoleMap, web_accessibility_to_native_subrole,
225 (BuildSubroleMap()));
226 RoleMap::iterator it = web_accessibility_to_native_subrole.find(role);
227 if (it != web_accessibility_to_native_subrole.end())
228 return it->second;
229 else
230 return nil;
231 }
232
233 // A mapping from an accessibility attribute to its method name. 49 // A mapping from an accessibility attribute to its method name.
234 NSDictionary* attributeToMethodNameMap = nil; 50 NSDictionary* attributeToMethodNameMap = nil;
235 51
236 } // namespace 52 } // namespace
237 53
238 @implementation BrowserAccessibilityCocoa 54 @implementation BrowserAccessibilityCocoa
239 55
240 + (void)initialize { 56 + (void)initialize {
241 const struct { 57 const struct {
242 NSString* attribute; 58 NSString* attribute;
(...skipping 469 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 bool isAriaPressedDefined; 528 bool isAriaPressedDefined;
713 bool isMixed; 529 bool isMixed;
714 browserAccessibility_->GetAriaTristate("aria-pressed", 530 browserAccessibility_->GetAriaTristate("aria-pressed",
715 &isAriaPressedDefined, 531 &isAriaPressedDefined,
716 &isMixed); 532 &isMixed);
717 if (isAriaPressedDefined) 533 if (isAriaPressedDefined)
718 return NSAccessibilityCheckBoxRole; 534 return NSAccessibilityCheckBoxRole;
719 else 535 else
720 return NSAccessibilityButtonRole; 536 return NSAccessibilityButtonRole;
721 } 537 }
722 return NativeRoleFromAXRole(role); 538 return [AXPlatformNodeCocoa nativeRoleFromAXRole:role];
723 } 539 }
724 540
725 // Returns a string indicating the role description of this object. 541 // Returns a string indicating the role description of this object.
726 - (NSString*)roleDescription { 542 - (NSString*)roleDescription {
727 NSString* role = [self role]; 543 NSString* role = [self role];
728 544
729 ContentClient* content_client = content::GetContentClient(); 545 ContentClient* content_client = content::GetContentClient();
730 546
731 // The following descriptions are specific to webkit. 547 // The following descriptions are specific to webkit.
732 if ([role isEqualToString:@"AXWebArea"]) { 548 if ([role isEqualToString:@"AXWebArea"]) {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 browserAccessibility_, ui::AX_ATTR_HTML_TAG); 704 browserAccessibility_, ui::AX_ATTR_HTML_TAG);
889 705
890 if (browserAccessibilityRole == ui::AX_ROLE_LIST) { 706 if (browserAccessibilityRole == ui::AX_ROLE_LIST) {
891 if ([htmlTag isEqualToString:@"dl"]) { 707 if ([htmlTag isEqualToString:@"dl"]) {
892 return @"AXDescriptionList"; 708 return @"AXDescriptionList";
893 } else { 709 } else {
894 return @"AXContentList"; 710 return @"AXContentList";
895 } 711 }
896 } 712 }
897 713
898 return NativeSubroleFromAXRole(browserAccessibilityRole); 714 return [AXPlatformNodeCocoa nativeSubroleFromAXRole:browserAccessibilityRole];
899 } 715 }
900 716
901 // Returns all tabs in this subtree. 717 // Returns all tabs in this subtree.
902 - (NSArray*)tabs { 718 - (NSArray*)tabs {
903 NSMutableArray* tabSubtree = [[[NSMutableArray alloc] init] autorelease]; 719 NSMutableArray* tabSubtree = [[[NSMutableArray alloc] init] autorelease];
904 720
905 if ([self internalRole] == ui::AX_ROLE_TAB) 721 if ([self internalRole] == ui::AX_ROLE_TAB)
906 [tabSubtree addObject:self]; 722 [tabSubtree addObject:self];
907 723
908 for (uint i=0; i < [[self children] count]; ++i) { 724 for (uint i=0; i < [[self children] count]; ++i) {
(...skipping 720 matching lines...) Expand 10 before | Expand all | Expand 10 after
1629 return [super hash]; 1445 return [super hash];
1630 return browserAccessibility_->GetId(); 1446 return browserAccessibility_->GetId();
1631 } 1447 }
1632 1448
1633 - (BOOL)accessibilityShouldUseUniqueId { 1449 - (BOOL)accessibilityShouldUseUniqueId {
1634 return YES; 1450 return YES;
1635 } 1451 }
1636 1452
1637 @end 1453 @end
1638 1454
OLDNEW
« no previous file with comments | « no previous file | ui/accessibility/accessibility.gyp » ('j') | ui/accessibility/accessibility.gyp » ('J')

Powered by Google App Engine
This is Rietveld 408576698