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