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

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

Issue 1134653003: Implement UIElementsForSearchPredicate accessibility APIs for OS X. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address feedback Created 5 years, 7 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
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/app/strings/grit/content_strings.h" 15 #include "content/app/strings/grit/content_strings.h"
16 #include "content/browser/accessibility/browser_accessibility_manager.h" 16 #include "content/browser/accessibility/browser_accessibility_manager.h"
17 #include "content/browser/accessibility/browser_accessibility_manager_mac.h" 17 #include "content/browser/accessibility/browser_accessibility_manager_mac.h"
18 #include "content/browser/accessibility/one_shot_accessibility_tree_search.h"
18 #include "content/public/common/content_client.h" 19 #include "content/public/common/content_client.h"
19 #import "ui/accessibility/platform/ax_platform_node_mac.h" 20 #import "ui/accessibility/platform/ax_platform_node_mac.h"
20 21
21 // See http://openradar.appspot.com/9896491. This SPI has been tested on 10.5, 22 // See http://openradar.appspot.com/9896491. This SPI has been tested on 10.5,
22 // 10.6, and 10.7. It allows accessibility clients to observe events posted on 23 // 10.6, and 10.7. It allows accessibility clients to observe events posted on
23 // this object. 24 // this object.
24 extern "C" void NSAccessibilityUnregisterUniqueIdForUIElement(id element); 25 extern "C" void NSAccessibilityUnregisterUniqueIdForUIElement(id element);
25 26
26 using ui::AXNodeData; 27 using ui::AXNodeData;
28 using content::AccessibilityMatchPredicate;
27 using content::BrowserAccessibility; 29 using content::BrowserAccessibility;
28 using content::BrowserAccessibilityDelegate; 30 using content::BrowserAccessibilityDelegate;
29 using content::BrowserAccessibilityManager; 31 using content::BrowserAccessibilityManager;
30 using content::BrowserAccessibilityManagerMac; 32 using content::BrowserAccessibilityManagerMac;
31 using content::ContentClient; 33 using content::ContentClient;
34 using content::OneShotAccessibilityTreeSearch;
32 typedef ui::AXStringAttribute StringAttribute; 35 typedef ui::AXStringAttribute StringAttribute;
33 36
34 namespace { 37 namespace {
35 38
39 // VoiceOver uses -1 to mean "no limit" for AXResultsLimit.
40 const int kAXResultsLimitNoLimit = -1;
41
36 // Returns an autoreleased copy of the AXNodeData's attribute. 42 // Returns an autoreleased copy of the AXNodeData's attribute.
37 NSString* NSStringForStringAttribute( 43 NSString* NSStringForStringAttribute(
38 BrowserAccessibility* browserAccessibility, 44 BrowserAccessibility* browserAccessibility,
39 StringAttribute attribute) { 45 StringAttribute attribute) {
40 return base::SysUTF8ToNSString( 46 return base::SysUTF8ToNSString(
41 browserAccessibility->GetStringAttribute(attribute)); 47 browserAccessibility->GetStringAttribute(attribute));
42 } 48 }
43 49
44 // GetState checks the bitmask used in AXNodeData to check 50 // GetState checks the bitmask used in AXNodeData to check
45 // if the given state was set on the accessibility object. 51 // if the given state was set on the accessibility object.
46 bool GetState(BrowserAccessibility* accessibility, ui::AXState state) { 52 bool GetState(BrowserAccessibility* accessibility, ui::AXState state) {
47 return ((accessibility->GetState() >> state) & 1); 53 return ((accessibility->GetState() >> state) & 1);
48 } 54 }
49 55
50 // A mapping from an accessibility attribute to its method name. 56 // A mapping from an accessibility attribute to its method name.
51 NSDictionary* attributeToMethodNameMap = nil; 57 NSDictionary* attributeToMethodNameMap = nil;
52 58
59 // Given a search key provided to AXUIElementCountForSearchPredicate or
60 // AXUIElementsForSearchPredicate, return a predicate that can be added
61 // to OneShotAccessibilityTreeSearch.
62 AccessibilityMatchPredicate PredicateForSearchKey(NSString* searchKey) {
63 if ([searchKey isEqualToString:@"AXAnyTypeSearchKey"]) {
64 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
65 return true;
66 };
67 } else if ([searchKey isEqualToString:@"AXBlockquoteSameLevelSearchKey"] ||
68 [searchKey isEqualToString:@"AXBlockquoteSearchKey"]) {
69 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
70 // TODO(dmazzoni): implement the "same level" part.
71 return current->GetRole() == ui::AX_ROLE_BLOCKQUOTE;
72 };
73 } else if ([searchKey isEqualToString:@"AXBoldFontSearchKey"]) {
74 // TODO(dmazzoni): implement this.
75 return nullptr;
76 } else if ([searchKey isEqualToString:@"AXButtonSearchKey"]) {
77 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
78 return (current->GetRole() == ui::AX_ROLE_BUTTON ||
79 current->GetRole() == ui::AX_ROLE_MENU_BUTTON ||
80 current->GetRole() == ui::AX_ROLE_POP_UP_BUTTON ||
81 current->GetRole() == ui::AX_ROLE_SWITCH ||
82 current->GetRole() == ui::AX_ROLE_TOGGLE_BUTTON);
83 };
84 } else if ([searchKey isEqualToString:@"AXCheckBoxSearchKey"]) {
85 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
86 return (current->GetRole() == ui::AX_ROLE_CHECK_BOX ||
87 current->GetRole() == ui::AX_ROLE_MENU_ITEM_CHECK_BOX);
88 };
89 } else if ([searchKey isEqualToString:@"AXControlSearchKey"]) {
90 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
91 if (current->IsControl())
92 return true;
93 if (current->HasState(ui::AX_STATE_FOCUSABLE) &&
94 current->GetRole() != ui::AX_ROLE_IMAGE_MAP_LINK &&
95 current->GetRole() != ui::AX_ROLE_LINK) {
96 return true;
97 }
98 return false;
99 };
100 } else if ([searchKey isEqualToString:@"AXDifferentTypeSearchKey"]) {
101 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
102 return current->GetRole() != start->GetRole();
103 };
104 } else if ([searchKey isEqualToString:@"AXFontChangeSearchKey"]) {
105 // TODO(dmazzoni): implement this.
106 return nullptr;
107 } else if ([searchKey isEqualToString:@"AXFontColorChangeSearchKey"]) {
108 // TODO(dmazzoni): implement this.
109 return nullptr;
110 } else if ([searchKey isEqualToString:@"AXFrameSearchKey"]) {
111 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
112 if (current->IsWebAreaForPresentationalIframe())
113 return false;
114 return (current->GetRole() == ui::AX_ROLE_WEB_AREA ||
115 current->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA);
116 };
117 } else if ([searchKey isEqualToString:@"AXGraphicSearchKey"]) {
118 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
119 return current->GetRole() == ui::AX_ROLE_IMAGE;
120 };
121 } else if ([searchKey isEqualToString:@"AXHeadingLevel1SearchKey"]) {
122 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
123 return (current->GetRole() == ui::AX_ROLE_HEADING &&
124 current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 1);
125 };
126 } else if ([searchKey isEqualToString:@"AXHeadingLevel2SearchKey"]) {
127 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
128 return (current->GetRole() == ui::AX_ROLE_HEADING &&
129 current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 2);
130 };
131 } else if ([searchKey isEqualToString:@"AXHeadingLevel3SearchKey"]) {
132 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
133 return (current->GetRole() == ui::AX_ROLE_HEADING &&
134 current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 3);
135 };
136 } else if ([searchKey isEqualToString:@"AXHeadingLevel4SearchKey"]) {
137 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
138 return (current->GetRole() == ui::AX_ROLE_HEADING &&
139 current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 4);
140 };
141 } else if ([searchKey isEqualToString:@"AXHeadingLevel5SearchKey"]) {
142 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
143 return (current->GetRole() == ui::AX_ROLE_HEADING &&
144 current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 5);
145 };
146 } else if ([searchKey isEqualToString:@"AXHeadingLevel6SearchKey"]) {
147 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
148 return (current->GetRole() == ui::AX_ROLE_HEADING &&
149 current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 6);
150 };
151 } else if ([searchKey isEqualToString:@"AXHeadingSameLevelSearchKey"]) {
152 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
153 return (current->GetRole() == ui::AX_ROLE_HEADING &&
154 start->GetRole() == ui::AX_ROLE_HEADING &&
155 (current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) ==
156 start->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL)));
157 };
158 } else if ([searchKey isEqualToString:@"AXHeadingSearchKey"]) {
159 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
160 return current->GetRole() == ui::AX_ROLE_HEADING;
161 };
162 } else if ([searchKey isEqualToString:@"AXHighlightedSearchKey"]) {
163 // TODO(dmazzoni): implement this.
164 return nullptr;
165 } else if ([searchKey isEqualToString:@"AXItalicFontSearchKey"]) {
166 // TODO(dmazzoni): implement this.
167 return nullptr;
168 } else if ([searchKey isEqualToString:@"AXLandmarkSearchKey"]) {
169 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
170 return (current->GetRole() == ui::AX_ROLE_APPLICATION ||
171 current->GetRole() == ui::AX_ROLE_BANNER ||
172 current->GetRole() == ui::AX_ROLE_COMPLEMENTARY ||
173 current->GetRole() == ui::AX_ROLE_CONTENT_INFO ||
174 current->GetRole() == ui::AX_ROLE_FORM ||
175 current->GetRole() == ui::AX_ROLE_MAIN ||
176 current->GetRole() == ui::AX_ROLE_NAVIGATION ||
177 current->GetRole() == ui::AX_ROLE_SEARCH);
178 };
179 } else if ([searchKey isEqualToString:@"AXLinkSearchKey"]) {
180 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
181 return current->GetRole() == ui::AX_ROLE_LINK;
182 };
183 } else if ([searchKey isEqualToString:@"AXListSearchKey"]) {
184 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
185 return current->GetRole() == ui::AX_ROLE_LIST;
186 };
187 } else if ([searchKey isEqualToString:@"AXLiveRegionSearchKey"]) {
188 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
189 return current->HasStringAttribute(ui::AX_ATTR_LIVE_STATUS);
190 };
191 } else if ([searchKey isEqualToString:@"AXMisspelledWordSearchKey"]) {
192 // TODO(dmazzoni): implement this.
193 return nullptr;
194 } else if ([searchKey isEqualToString:@"AXOutlineSearchKey"]) {
195 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
196 return current->GetRole() == ui::AX_ROLE_TREE;
197 };
198 } else if ([searchKey isEqualToString:@"AXPlainTextSearchKey"]) {
199 // TODO(dmazzoni): implement this.
200 return nullptr;
201 } else if ([searchKey isEqualToString:@"AXRadioGroupSearchKey"]) {
202 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
203 return current->GetRole() == ui::AX_ROLE_RADIO_GROUP;
204 };
205 } else if ([searchKey isEqualToString:@"AXSameTypeSearchKey"]) {
206 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
207 return current->GetRole() == start->GetRole();
208 };
209 } else if ([searchKey isEqualToString:@"AXStaticTextSearchKey"]) {
210 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
211 return current->GetRole() == ui::AX_ROLE_STATIC_TEXT;
212 };
213 } else if ([searchKey isEqualToString:@"AXStyleChangeSearchKey"]) {
214 // TODO(dmazzoni): implement this.
215 return nullptr;
216 } else if ([searchKey isEqualToString:@"AXTableSameLevelSearchKey"]) {
217 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
218 // TODO(dmazzoni): implement the "same level" part.
219 return current->GetRole() == ui::AX_ROLE_GRID ||
220 current->GetRole() == ui::AX_ROLE_TABLE;
221 };
222 } else if ([searchKey isEqualToString:@"AXTableSearchKey"]) {
223 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
224 return current->GetRole() == ui::AX_ROLE_GRID ||
225 current->GetRole() == ui::AX_ROLE_TABLE;
226 };
227 } else if ([searchKey isEqualToString:@"AXTextFieldSearchKey"]) {
228 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
229 return current->GetRole() == ui::AX_ROLE_TEXT_FIELD;
230 };
231 } else if ([searchKey isEqualToString:@"AXUnderlineSearchKey"]) {
232 // TODO(dmazzoni): implement this.
233 return nullptr;
234 } else if ([searchKey isEqualToString:@"AXUnvisitedLinkSearchKey"]) {
235 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
236 return (current->GetRole() == ui::AX_ROLE_LINK &&
237 !current->HasState(ui::AX_STATE_VISITED));
238 };
239 } else if ([searchKey isEqualToString:@"AXVisitedLinkSearchKey"]) {
240 return [](BrowserAccessibility* start, BrowserAccessibility* current) {
241 return (current->GetRole() == ui::AX_ROLE_LINK &&
242 current->HasState(ui::AX_STATE_VISITED));
243 };
244 }
245
246 return nullptr;
247 }
248
249 // Initialize a OneShotAccessibilityTreeSearch object given the parameters
250 // passed to AXUIElementCountForSearchPredicate or
251 // AXUIElementsForSearchPredicate. Return true on success.
252 bool InitializeAccessibilityTreeSearch(
253 OneShotAccessibilityTreeSearch* search,
254 id parameter) {
255 if (![parameter isKindOfClass:[NSDictionary class]])
256 return false;
257 NSDictionary* dictionary = parameter;
258
259 id startElementParameter = [dictionary objectForKey:@"AXStartElement"];
260 BrowserAccessibility* startNode = nullptr;
261 if ([startElementParameter isKindOfClass:[BrowserAccessibilityCocoa class]]) {
262 BrowserAccessibilityCocoa* startNodeCocoa =
263 (BrowserAccessibilityCocoa*)startElementParameter;
264 startNode = [startNodeCocoa browserAccessibility];
265 }
266
267 bool immediateDescendantsOnly = false;
268 NSNumber *immediateDescendantsOnlyParameter =
269 [dictionary objectForKey:@"AXImmediateDescendantsOnly"];
270 if ([immediateDescendantsOnlyParameter isKindOfClass:[NSNumber class]])
271 immediateDescendantsOnly = [immediateDescendantsOnlyParameter boolValue];
272
273 bool visibleOnly = false;
274 NSNumber *visibleOnlyParameter = [dictionary objectForKey:@"AXVisibleOnly"];
275 if ([visibleOnlyParameter isKindOfClass:[NSNumber class]])
276 visibleOnly = [visibleOnlyParameter boolValue];
277
278 content::OneShotAccessibilityTreeSearch::Direction direction =
279 content::OneShotAccessibilityTreeSearch::FORWARDS;
280 NSString* directionParameter = [dictionary objectForKey:@"AXDirection"];
281 if ([directionParameter isKindOfClass:[NSString class]]) {
282 if ([directionParameter isEqualToString:@"AXDirectionNext"])
283 direction = content::OneShotAccessibilityTreeSearch::FORWARDS;
284 else if ([directionParameter isEqualToString:@"AXDirectionPrevious"])
285 direction = content::OneShotAccessibilityTreeSearch::BACKWARDS;
286 }
287
288 int resultsLimit = kAXResultsLimitNoLimit;
289 NSNumber* resultsLimitParameter = [dictionary objectForKey:@"AXResultsLimit"];
290 if ([resultsLimitParameter isKindOfClass:[NSNumber class]])
291 resultsLimit = [resultsLimitParameter intValue];
292
293 std::string searchText;
294 NSString* searchTextParameter = [dictionary objectForKey:@"AXSearchText"];
295 if ([searchTextParameter isKindOfClass:[NSString class]])
296 searchText = base::SysNSStringToUTF8(searchTextParameter);
297
298 search->SetStartNode(startNode);
299 search->SetDirection(direction);
300 search->SetImmediateDescendantsOnly(immediateDescendantsOnly);
301 search->SetVisibleOnly(visibleOnly);
302 search->SetSearchText(searchText);
303
304 // Mac uses resultsLimit == -1 for unlimited, that that's
305 // the default for OneShotAccessibilityTreeSearch already.
306 // Only set the results limit if it's nonnegative.
307 if (resultsLimit >= 0)
308 search->SetResultLimit(resultsLimit);
309
310 id searchKey = [dictionary objectForKey:@"AXSearchKey"];
311 if ([searchKey isKindOfClass:[NSString class]]) {
312 AccessibilityMatchPredicate predicate =
313 PredicateForSearchKey((NSString*)searchKey);
314 if (predicate)
315 search->AddPredicate(predicate);
316 } else if ([searchKey isKindOfClass:[NSArray class]]) {
317 size_t searchKeyCount = static_cast<size_t>([searchKey count]);
318 for (size_t i = 0; i < searchKeyCount; ++i) {
319 id key = [searchKey objectAtIndex:i];
320 if ([key isKindOfClass:[NSString class]]) {
321 AccessibilityMatchPredicate predicate =
322 PredicateForSearchKey((NSString*)key);
323 if (predicate)
324 search->AddPredicate(predicate);
325 }
326 }
327 }
328
329 return true;
330 }
331
53 } // namespace 332 } // namespace
54 333
55 @implementation BrowserAccessibilityCocoa 334 @implementation BrowserAccessibilityCocoa
56 335
57 + (void)initialize { 336 + (void)initialize {
58 const struct { 337 const struct {
59 NSString* attribute; 338 NSString* attribute;
60 NSString* methodName; 339 NSString* methodName;
61 } attributeToMethodNameContainer[] = { 340 } attributeToMethodNameContainer[] = {
62 { NSAccessibilityChildrenAttribute, @"children" }, 341 { NSAccessibilityChildrenAttribute, @"children" },
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
550 - (ui::AXRole)internalRole { 829 - (ui::AXRole)internalRole {
551 return static_cast<ui::AXRole>(browserAccessibility_->GetRole()); 830 return static_cast<ui::AXRole>(browserAccessibility_->GetRole());
552 } 831 }
553 832
554 - (content::BrowserAccessibilityDelegate*)delegate { 833 - (content::BrowserAccessibilityDelegate*)delegate {
555 return browserAccessibility_->manager() ? 834 return browserAccessibility_->manager() ?
556 browserAccessibility_->manager()->delegate() : 835 browserAccessibility_->manager()->delegate() :
557 nil; 836 nil;
558 } 837 }
559 838
839 - (content::BrowserAccessibility*)browserAccessibility {
840 return browserAccessibility_;
841 }
842
560 - (NSPoint)pointInScreen:(NSPoint)origin 843 - (NSPoint)pointInScreen:(NSPoint)origin
561 size:(NSSize)size { 844 size:(NSSize)size {
562 if (!browserAccessibility_) 845 if (!browserAccessibility_)
563 return NSZeroPoint; 846 return NSZeroPoint;
564 847
565 // Get the delegate for the topmost BrowserAccessibilityManager, because 848 // Get the delegate for the topmost BrowserAccessibilityManager, because
566 // that's the only one that can convert points to their origin in the screen. 849 // that's the only one that can convert points to their origin in the screen.
567 BrowserAccessibilityDelegate* delegate = 850 BrowserAccessibilityDelegate* delegate =
568 browserAccessibility_->manager()->GetDelegateFromRootManager(); 851 browserAccessibility_->manager()->GetDelegateFromRootManager();
569 if (delegate) { 852 if (delegate) {
(...skipping 636 matching lines...) Expand 10 before | Expand all | Expand 10 after
1206 NSRange range = [(NSValue*)parameter rangeValue]; 1489 NSRange range = [(NSValue*)parameter rangeValue];
1207 gfx::Rect rect = browserAccessibility_->GetGlobalBoundsForRange( 1490 gfx::Rect rect = browserAccessibility_->GetGlobalBoundsForRange(
1208 range.location, range.length); 1491 range.location, range.length);
1209 NSPoint origin = NSMakePoint(rect.x(), rect.y()); 1492 NSPoint origin = NSMakePoint(rect.x(), rect.y());
1210 NSSize size = NSMakeSize(rect.width(), rect.height()); 1493 NSSize size = NSMakeSize(rect.width(), rect.height());
1211 NSPoint pointInScreen = [self pointInScreen:origin size:size]; 1494 NSPoint pointInScreen = [self pointInScreen:origin size:size];
1212 NSRect nsrect = NSMakeRect( 1495 NSRect nsrect = NSMakeRect(
1213 pointInScreen.x, pointInScreen.y, rect.width(), rect.height()); 1496 pointInScreen.x, pointInScreen.y, rect.width(), rect.height());
1214 return [NSValue valueWithRect:nsrect]; 1497 return [NSValue valueWithRect:nsrect];
1215 } 1498 }
1499 if ([attribute isEqualToString:@"AXUIElementCountForSearchPredicate"]) {
1500 OneShotAccessibilityTreeSearch search(browserAccessibility_->manager());
1501 if (InitializeAccessibilityTreeSearch(&search, parameter))
1502 return [NSNumber numberWithInt:search.CountMatches()];
1503 return nil;
1504 }
1505
1506 if ([attribute isEqualToString:@"AXUIElementsForSearchPredicate"]) {
1507 OneShotAccessibilityTreeSearch search(browserAccessibility_->manager());
1508 if (InitializeAccessibilityTreeSearch(&search, parameter)) {
1509 size_t count = search.CountMatches();
1510 NSMutableArray* result = [NSMutableArray arrayWithCapacity:count];
1511 for (size_t i = 0; i < count; ++i) {
1512 BrowserAccessibility* match = search.GetMatchAtIndex(i);
1513 [result addObject:match->ToBrowserAccessibilityCocoa()];
1514 }
1515 return result;
1516 }
1517 return nil;
1518 }
1216 1519
1217 // TODO(dtseng): support the following attributes. 1520 // TODO(dtseng): support the following attributes.
1218 if ([attribute isEqualTo: 1521 if ([attribute isEqualTo:
1219 NSAccessibilityRangeForPositionParameterizedAttribute] || 1522 NSAccessibilityRangeForPositionParameterizedAttribute] ||
1220 [attribute isEqualTo: 1523 [attribute isEqualTo:
1221 NSAccessibilityRangeForIndexParameterizedAttribute] || 1524 NSAccessibilityRangeForIndexParameterizedAttribute] ||
1222 [attribute isEqualTo:NSAccessibilityRTFForRangeParameterizedAttribute] || 1525 [attribute isEqualTo:NSAccessibilityRTFForRangeParameterizedAttribute] ||
1223 [attribute isEqualTo: 1526 [attribute isEqualTo:
1224 NSAccessibilityStyleRangeForIndexParameterizedAttribute]) { 1527 NSAccessibilityStyleRangeForIndexParameterizedAttribute]) {
1225 return nil; 1528 return nil;
1226 } 1529 }
1227 return nil; 1530 return nil;
1228 } 1531 }
1229 1532
1230 // Returns an array of parameterized attributes names that this object will 1533 // Returns an array of parameterized attributes names that this object will
1231 // respond to. 1534 // respond to.
1232 - (NSArray*)accessibilityParameterizedAttributeNames { 1535 - (NSArray*)accessibilityParameterizedAttributeNames {
1233 if (!browserAccessibility_) 1536 if (!browserAccessibility_)
1234 return nil; 1537 return nil;
1235 1538
1539 // General attributes.
1540 NSMutableArray* ret = [NSMutableArray arrayWithObjects:
1541 @"AXUIElementCountForSearchPredicate",
1542 @"AXUIElementsForSearchPredicate",
1543 nil];
1544
1236 if ([[self role] isEqualToString:NSAccessibilityTableRole] || 1545 if ([[self role] isEqualToString:NSAccessibilityTableRole] ||
1237 [[self role] isEqualToString:NSAccessibilityGridRole]) { 1546 [[self role] isEqualToString:NSAccessibilityGridRole]) {
1238 return [NSArray arrayWithObjects: 1547 [ret addObjectsFromArray:[NSArray arrayWithObjects:
1239 NSAccessibilityCellForColumnAndRowParameterizedAttribute, 1548 NSAccessibilityCellForColumnAndRowParameterizedAttribute,
1240 nil]; 1549 nil]];
1241 } 1550 }
1242 if ([[self role] isEqualToString:NSAccessibilityTextFieldRole]) { 1551 if ([[self role] isEqualToString:NSAccessibilityTextFieldRole]) {
1243 return [NSArray arrayWithObjects: 1552 [ret addObjectsFromArray:[NSArray arrayWithObjects:
1244 NSAccessibilityLineForIndexParameterizedAttribute, 1553 NSAccessibilityLineForIndexParameterizedAttribute,
1245 NSAccessibilityRangeForLineParameterizedAttribute, 1554 NSAccessibilityRangeForLineParameterizedAttribute,
1246 NSAccessibilityStringForRangeParameterizedAttribute, 1555 NSAccessibilityStringForRangeParameterizedAttribute,
1247 NSAccessibilityRangeForPositionParameterizedAttribute, 1556 NSAccessibilityRangeForPositionParameterizedAttribute,
1248 NSAccessibilityRangeForIndexParameterizedAttribute, 1557 NSAccessibilityRangeForIndexParameterizedAttribute,
1249 NSAccessibilityBoundsForRangeParameterizedAttribute, 1558 NSAccessibilityBoundsForRangeParameterizedAttribute,
1250 NSAccessibilityRTFForRangeParameterizedAttribute, 1559 NSAccessibilityRTFForRangeParameterizedAttribute,
1251 NSAccessibilityAttributedStringForRangeParameterizedAttribute, 1560 NSAccessibilityAttributedStringForRangeParameterizedAttribute,
1252 NSAccessibilityStyleRangeForIndexParameterizedAttribute, 1561 NSAccessibilityStyleRangeForIndexParameterizedAttribute,
1253 nil]; 1562 nil]];
1254 } 1563 }
1255 if ([self internalRole] == ui::AX_ROLE_STATIC_TEXT) { 1564 if ([self internalRole] == ui::AX_ROLE_STATIC_TEXT) {
1256 return [NSArray arrayWithObjects: 1565 [ret addObjectsFromArray:[NSArray arrayWithObjects:
1257 NSAccessibilityBoundsForRangeParameterizedAttribute, 1566 NSAccessibilityBoundsForRangeParameterizedAttribute,
1258 nil]; 1567 nil]];
1259 } 1568 }
1260 return nil; 1569 return ret;
1261 } 1570 }
1262 1571
1263 // Returns an array of action names that this object will respond to. 1572 // Returns an array of action names that this object will respond to.
1264 - (NSArray*)accessibilityActionNames { 1573 - (NSArray*)accessibilityActionNames {
1265 if (!browserAccessibility_) 1574 if (!browserAccessibility_)
1266 return nil; 1575 return nil;
1267 1576
1268 NSMutableArray* ret = 1577 NSMutableArray* ret =
1269 [NSMutableArray arrayWithObject:NSAccessibilityShowMenuAction]; 1578 [NSMutableArray arrayWithObject:NSAccessibilityShowMenuAction];
1270 NSString* role = [self role]; 1579 NSString* role = [self role];
(...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after
1662 if (!browserAccessibility_) 1971 if (!browserAccessibility_)
1663 return [super hash]; 1972 return [super hash];
1664 return browserAccessibility_->GetId(); 1973 return browserAccessibility_->GetId();
1665 } 1974 }
1666 1975
1667 - (BOOL)accessibilityShouldUseUniqueId { 1976 - (BOOL)accessibilityShouldUseUniqueId {
1668 return YES; 1977 return YES;
1669 } 1978 }
1670 1979
1671 @end 1980 @end
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698