AX: Make AXIsolatedTree compile again
[WebKit-https.git] / Source / WebCore / accessibility / mac / WebAccessibilityObjectWrapperBase.mm
1 /*
2  * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "config.h"
30 #import "WebAccessibilityObjectWrapperBase.h"
31
32 #if ENABLE(ACCESSIBILITY)
33
34 #import "AXIsolatedTree.h"
35 #import "AXIsolatedTreeNode.h"
36 #import "AXObjectCache.h"
37 #import "AccessibilityARIAGridRow.h"
38 #import "AccessibilityList.h"
39 #import "AccessibilityListBox.h"
40 #import "AccessibilityObjectInterface.h"
41 #import "AccessibilityRenderObject.h"
42 #import "AccessibilityScrollView.h"
43 #import "AccessibilitySpinButton.h"
44 #import "AccessibilityTable.h"
45 #import "AccessibilityTableCell.h"
46 #import "AccessibilityTableColumn.h"
47 #import "AccessibilityTableRow.h"
48 #import "Chrome.h"
49 #import "ChromeClient.h"
50 #import "ColorMac.h"
51 #import "ContextMenuController.h"
52 #import "Editing.h"
53 #import "Font.h"
54 #import "FontCascade.h"
55 #import "Frame.h"
56 #import "FrameLoaderClient.h"
57 #import "FrameSelection.h"
58 #import "HTMLNames.h"
59 #import "LayoutRect.h"
60 #import "LocalizedStrings.h"
61 #import "Page.h"
62 #import "RenderTextControl.h"
63 #import "RenderView.h"
64 #import "RenderWidget.h"
65 #import "ScrollView.h"
66 #import "TextCheckerClient.h"
67 #import "TextCheckingHelper.h"
68 #import "VisibleUnits.h"
69 #import "WebCoreFrameView.h"
70
71 #if PLATFORM(MAC)
72 #import <pal/spi/mac/HIServicesSPI.h>
73 #else
74 #import "WAKView.h"
75 #import "WAKWindow.h"
76 #endif
77
78 using namespace WebCore;
79 using namespace HTMLNames;
80
81 // Search Keys
82 #ifndef NSAccessibilityAnyTypeSearchKey
83 #define NSAccessibilityAnyTypeSearchKey @"AXAnyTypeSearchKey"
84 #endif
85
86 #ifndef NSAccessibilityArticleSearchKey
87 #define NSAccessibilityArticleSearchKey @"AXArticleSearchKey"
88 #endif
89
90 #ifndef NSAccessibilityBlockquoteSameLevelSearchKey
91 #define NSAccessibilityBlockquoteSameLevelSearchKey @"AXBlockquoteSameLevelSearchKey"
92 #endif
93
94 #ifndef NSAccessibilityBlockquoteSearchKey
95 #define NSAccessibilityBlockquoteSearchKey @"AXBlockquoteSearchKey"
96 #endif
97
98 #ifndef NSAccessibilityBoldFontSearchKey
99 #define NSAccessibilityBoldFontSearchKey @"AXBoldFontSearchKey"
100 #endif
101
102 #ifndef NSAccessibilityButtonSearchKey
103 #define NSAccessibilityButtonSearchKey @"AXButtonSearchKey"
104 #endif
105
106 #ifndef NSAccessibilityCheckBoxSearchKey
107 #define NSAccessibilityCheckBoxSearchKey @"AXCheckBoxSearchKey"
108 #endif
109
110 #ifndef NSAccessibilityControlSearchKey
111 #define NSAccessibilityControlSearchKey @"AXControlSearchKey"
112 #endif
113
114 #ifndef NSAccessibilityDifferentTypeSearchKey
115 #define NSAccessibilityDifferentTypeSearchKey @"AXDifferentTypeSearchKey"
116 #endif
117
118 #ifndef NSAccessibilityFontChangeSearchKey
119 #define NSAccessibilityFontChangeSearchKey @"AXFontChangeSearchKey"
120 #endif
121
122 #ifndef NSAccessibilityFontColorChangeSearchKey
123 #define NSAccessibilityFontColorChangeSearchKey @"AXFontColorChangeSearchKey"
124 #endif
125
126 #ifndef NSAccessibilityFrameSearchKey
127 #define NSAccessibilityFrameSearchKey @"AXFrameSearchKey"
128 #endif
129
130 #ifndef NSAccessibilityGraphicSearchKey
131 #define NSAccessibilityGraphicSearchKey @"AXGraphicSearchKey"
132 #endif
133
134 #ifndef NSAccessibilityHeadingLevel1SearchKey
135 #define NSAccessibilityHeadingLevel1SearchKey @"AXHeadingLevel1SearchKey"
136 #endif
137
138 #ifndef NSAccessibilityHeadingLevel2SearchKey
139 #define NSAccessibilityHeadingLevel2SearchKey @"AXHeadingLevel2SearchKey"
140 #endif
141
142 #ifndef NSAccessibilityHeadingLevel3SearchKey
143 #define NSAccessibilityHeadingLevel3SearchKey @"AXHeadingLevel3SearchKey"
144 #endif
145
146 #ifndef NSAccessibilityHeadingLevel4SearchKey
147 #define NSAccessibilityHeadingLevel4SearchKey @"AXHeadingLevel4SearchKey"
148 #endif
149
150 #ifndef NSAccessibilityHeadingLevel5SearchKey
151 #define NSAccessibilityHeadingLevel5SearchKey @"AXHeadingLevel5SearchKey"
152 #endif
153
154 #ifndef NSAccessibilityHeadingLevel6SearchKey
155 #define NSAccessibilityHeadingLevel6SearchKey @"AXHeadingLevel6SearchKey"
156 #endif
157
158 #ifndef NSAccessibilityHeadingSameLevelSearchKey
159 #define NSAccessibilityHeadingSameLevelSearchKey @"AXHeadingSameLevelSearchKey"
160 #endif
161
162 #ifndef NSAccessibilityHeadingSearchKey
163 #define NSAccessibilityHeadingSearchKey @"AXHeadingSearchKey"
164 #endif
165
166 #ifndef NSAccessibilityHighlightedSearchKey
167 #define NSAccessibilityHighlightedSearchKey @"AXHighlightedSearchKey"
168 #endif
169
170 #ifndef NSAccessibilityKeyboardFocusableSearchKey
171 #define NSAccessibilityKeyboardFocusableSearchKey @"AXKeyboardFocusableSearchKey"
172 #endif
173
174 #ifndef NSAccessibilityItalicFontSearchKey
175 #define NSAccessibilityItalicFontSearchKey @"AXItalicFontSearchKey"
176 #endif
177
178 #ifndef NSAccessibilityLandmarkSearchKey
179 #define NSAccessibilityLandmarkSearchKey @"AXLandmarkSearchKey"
180 #endif
181
182 #ifndef NSAccessibilityLinkSearchKey
183 #define NSAccessibilityLinkSearchKey @"AXLinkSearchKey"
184 #endif
185
186 #ifndef NSAccessibilityListSearchKey
187 #define NSAccessibilityListSearchKey @"AXListSearchKey"
188 #endif
189
190 #ifndef NSAccessibilityLiveRegionSearchKey
191 #define NSAccessibilityLiveRegionSearchKey @"AXLiveRegionSearchKey"
192 #endif
193
194 #ifndef NSAccessibilityMisspelledWordSearchKey
195 #define NSAccessibilityMisspelledWordSearchKey @"AXMisspelledWordSearchKey"
196 #endif
197
198 #ifndef NSAccessibilityOutlineSearchKey
199 #define NSAccessibilityOutlineSearchKey @"AXOutlineSearchKey"
200 #endif
201
202 #ifndef NSAccessibilityPlainTextSearchKey
203 #define NSAccessibilityPlainTextSearchKey @"AXPlainTextSearchKey"
204 #endif
205
206 #ifndef NSAccessibilityRadioGroupSearchKey
207 #define NSAccessibilityRadioGroupSearchKey @"AXRadioGroupSearchKey"
208 #endif
209
210 #ifndef NSAccessibilitySameTypeSearchKey
211 #define NSAccessibilitySameTypeSearchKey @"AXSameTypeSearchKey"
212 #endif
213
214 #ifndef NSAccessibilityStaticTextSearchKey
215 #define NSAccessibilityStaticTextSearchKey @"AXStaticTextSearchKey"
216 #endif
217
218 #ifndef NSAccessibilityStyleChangeSearchKey
219 #define NSAccessibilityStyleChangeSearchKey @"AXStyleChangeSearchKey"
220 #endif
221
222 #ifndef NSAccessibilityTableSameLevelSearchKey
223 #define NSAccessibilityTableSameLevelSearchKey @"AXTableSameLevelSearchKey"
224 #endif
225
226 #ifndef NSAccessibilityTableSearchKey
227 #define NSAccessibilityTableSearchKey @"AXTableSearchKey"
228 #endif
229
230 #ifndef NSAccessibilityTextFieldSearchKey
231 #define NSAccessibilityTextFieldSearchKey @"AXTextFieldSearchKey"
232 #endif
233
234 #ifndef NSAccessibilityUnderlineSearchKey
235 #define NSAccessibilityUnderlineSearchKey @"AXUnderlineSearchKey"
236 #endif
237
238 #ifndef NSAccessibilityUnvisitedLinkSearchKey
239 #define NSAccessibilityUnvisitedLinkSearchKey @"AXUnvisitedLinkSearchKey"
240 #endif
241
242 #ifndef NSAccessibilityVisitedLinkSearchKey
243 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
244 #endif
245
246 // Search
247 #ifndef NSAccessibilityImmediateDescendantsOnly
248 #define NSAccessibilityImmediateDescendantsOnly @"AXImmediateDescendantsOnly"
249 #endif
250
251 #define _axBackingObject self.axBackingObject
252
253 static NSArray *convertMathPairsToNSArray(const AccessibilityObject::AccessibilityMathMultiscriptPairs& pairs, NSString *subscriptKey, NSString *superscriptKey)
254 {
255     NSMutableArray *array = [NSMutableArray arrayWithCapacity:pairs.size()];
256     for (const auto& pair : pairs) {
257         NSMutableDictionary *pairDictionary = [NSMutableDictionary dictionary];
258         if (pair.first && pair.first->wrapper() && !pair.first->accessibilityIsIgnored())
259             [pairDictionary setObject:pair.first->wrapper() forKey:subscriptKey];
260         if (pair.second && pair.second->wrapper() && !pair.second->accessibilityIsIgnored())
261             [pairDictionary setObject:pair.second->wrapper() forKey:superscriptKey];
262         [array addObject:pairDictionary];
263     }
264     return array;
265 }
266
267 static void addChildToArray(AccessibilityObjectInterface& child, RetainPtr<NSMutableArray> array)
268 {
269     WebAccessibilityObjectWrapper *wrapper = child.wrapper();
270     // We want to return the attachment view instead of the object representing the attachment,
271     // otherwise, we get palindrome errors in the AX hierarchy.
272     if (child.isAttachment() && [wrapper attachmentView])
273         [array.get() addObject:[wrapper attachmentView]];
274     else if (wrapper)
275         [array.get() addObject:wrapper];
276 }
277
278 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
279 NSArray *convertToNSArray(const Vector<RefPtr<WebCore::AXIsolatedTreeNode>>& children)
280 {
281     NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:children.size()];
282     for (auto& child : children)
283         addChildToArray(*child, result);
284     return [result autorelease];
285 }
286 #endif
287
288 NSArray *convertToNSArray(const WebCore::AccessibilityObject::AccessibilityChildrenVector& children)
289 {
290     NSMutableArray *result = [[NSMutableArray alloc] initWithCapacity:children.size()];
291     for (auto& child : children)
292         addChildToArray(*child, result);
293     return [result autorelease];
294 }
295
296 @implementation WebAccessibilityObjectWrapperBase
297
298 @synthesize identifier=_identifier;
299 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
300 @synthesize isolatedTreeIdentifier=_isolatedTreeIdentifier;
301 #endif
302
303 - (id)initWithAccessibilityObject:(AccessibilityObject*)axObject
304 {
305     if (!(self = [super init]))
306         return nil;
307
308     m_object = axObject;
309     _identifier = m_object->axObjectID();
310
311     return self;
312 }
313
314 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
315 - (RefPtr<WebCore::AXIsolatedTreeNode>)isolatedTreeNode
316 {
317     RELEASE_ASSERT(!isMainThread());
318
319     if (!_identifier)
320         return nullptr;
321
322     if (m_isolatedTreeNode)
323         return m_isolatedTreeNode;
324
325     m_isolatedTreeNode = AXIsolatedTree::nodeInTreeForID(_isolatedTreeIdentifier, _identifier);
326     return m_isolatedTreeNode;
327 }
328 #endif
329
330 - (void)detach
331 {
332     m_object = nullptr;
333     _identifier = 0;
334
335 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
336     m_isolatedTreeNode = nullptr;
337     _isolatedTreeIdentifier = 0;
338 #endif
339 }
340
341 - (BOOL)updateObjectBackingStore
342 {
343 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
344     if (_AXUIElementRequestServicedBySecondaryAXThread()) {
345         RELEASE_ASSERT(!isMainThread());
346         if (auto treeNode = self.isolatedTreeNode) {
347             if (auto tree = treeNode->tree())
348                 tree->applyPendingChanges();
349         }
350         return _identifier;
351     }
352 #endif
353     
354     // Calling updateBackingStore() can invalidate this element so self must be retained.
355     // If it does become invalidated, m_object will be nil.
356     CFRetain((__bridge CFTypeRef)self);
357     CFAutorelease((__bridge CFTypeRef)self);
358
359     if (!m_object)
360         return NO;
361     
362     m_object->updateBackingStore();
363     if (!m_object)
364         return NO;
365     
366     return YES;
367 }
368
369 - (id)attachmentView
370 {
371     return nil;
372 }
373
374 - (AccessibilityObject*)accessibilityObject
375 {
376 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
377     ASSERT(!_AXUIElementRequestServicedBySecondaryAXThread());
378 #endif
379     return m_object;
380 }
381
382 // This should be the "visible" text that's actually on the screen if possible.
383 // If there's alternative text, that can override the title.
384 - (NSString *)baseAccessibilityTitle
385 {
386     return _axBackingObject->titleAttributeValue();
387 }
388
389 - (WebCore::AccessibilityObjectInterface*)axBackingObject
390 {
391 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
392     if (_AXUIElementRequestServicedBySecondaryAXThread())
393         return self.isolatedTreeNode.get();
394 #endif
395     return m_object;
396 }
397
398 - (NSString *)baseAccessibilityDescription
399 {
400     return _axBackingObject->descriptionAttributeValue();
401 }
402
403 - (NSArray<NSString *> *)baseAccessibilitySpeechHint
404 {
405     return [(NSString *)_axBackingObject->speechHintAttributeValue() componentsSeparatedByString:@" "];
406 }
407
408 - (NSString *)baseAccessibilityHelpText
409 {
410     return _axBackingObject->helpTextAttributeValue();
411 }
412
413 struct PathConversionInfo {
414     WebAccessibilityObjectWrapperBase *wrapper;
415     CGMutablePathRef path;
416 };
417
418 static void convertPathToScreenSpaceFunction(PathConversionInfo& conversion, const PathElement& element)
419 {
420     WebAccessibilityObjectWrapperBase *wrapper = conversion.wrapper;
421     CGMutablePathRef newPath = conversion.path;
422     FloatRect rect;
423     switch (element.type) {
424     case PathElementMoveToPoint:
425     {
426         rect = FloatRect(element.points[0], FloatSize());
427         CGPoint newPoint = [wrapper convertRectToSpace:rect space:AccessibilityConversionSpace::Screen].origin;
428         CGPathMoveToPoint(newPath, nil, newPoint.x, newPoint.y);
429         break;
430     }
431     case PathElementAddLineToPoint:
432     {
433         rect = FloatRect(element.points[0], FloatSize());
434         CGPoint newPoint = [wrapper convertRectToSpace:rect space:AccessibilityConversionSpace::Screen].origin;
435         CGPathAddLineToPoint(newPath, nil, newPoint.x, newPoint.y);
436         break;
437     }
438     case PathElementAddQuadCurveToPoint:
439     {
440         rect = FloatRect(element.points[0], FloatSize());
441         CGPoint newPoint1 = [wrapper convertRectToSpace:rect space:AccessibilityConversionSpace::Screen].origin;
442
443         rect = FloatRect(element.points[1], FloatSize());
444         CGPoint newPoint2 = [wrapper convertRectToSpace:rect space:AccessibilityConversionSpace::Screen].origin;
445         CGPathAddQuadCurveToPoint(newPath, nil, newPoint1.x, newPoint1.y, newPoint2.x, newPoint2.y);
446         break;
447     }
448     case PathElementAddCurveToPoint:
449     {
450         rect = FloatRect(element.points[0], FloatSize());
451         CGPoint newPoint1 = [wrapper convertRectToSpace:rect space:AccessibilityConversionSpace::Screen].origin;
452
453         rect = FloatRect(element.points[1], FloatSize());
454         CGPoint newPoint2 = [wrapper convertRectToSpace:rect space:AccessibilityConversionSpace::Screen].origin;
455
456         rect = FloatRect(element.points[2], FloatSize());
457         CGPoint newPoint3 = [wrapper convertRectToSpace:rect space:AccessibilityConversionSpace::Screen].origin;
458         CGPathAddCurveToPoint(newPath, nil, newPoint1.x, newPoint1.y, newPoint2.x, newPoint2.y, newPoint3.x, newPoint3.y);
459         break;
460     }
461     case PathElementCloseSubpath:
462     {
463         CGPathCloseSubpath(newPath);
464         break;
465     }
466     }
467 }
468
469 - (CGPathRef)convertPathToScreenSpace:(Path &)path
470 {
471     PathConversionInfo conversion = { self, CGPathCreateMutable() };
472     path.apply([&conversion](const PathElement& pathElement) {
473         convertPathToScreenSpaceFunction(conversion, pathElement);
474     });
475     CFAutorelease(conversion.path);
476     return conversion.path;
477 }
478
479 - (id)_accessibilityWebDocumentView
480 {
481     ASSERT_NOT_REACHED();
482     // Overridden by sub-classes
483     return nil;
484 }
485
486 - (CGRect)convertRectToSpace:(WebCore::FloatRect &)rect space:(AccessibilityConversionSpace)space
487 {
488     if (!m_object)
489         return CGRectZero;
490     
491     CGSize size = CGSizeMake(rect.size().width(), rect.size().height());
492     CGPoint point = CGPointMake(rect.x(), rect.y());
493     
494     CGRect cgRect = CGRectMake(point.x, point.y, size.width, size.height);
495
496     // WebKit1 code path... platformWidget() exists.
497     FrameView* frameView = m_object->documentFrameView();
498 #if PLATFORM(IOS_FAMILY)
499     WAKView* documentView = frameView ? frameView->documentView() : nullptr;
500     if (documentView) {
501         cgRect = [documentView convertRect:cgRect toView:nil];
502         
503         // we need the web document view to give us our final screen coordinates
504         // because that can take account of the scroller
505         id webDocument = [self _accessibilityWebDocumentView];
506         if (webDocument)
507             cgRect = [webDocument convertRect:cgRect toView:nil];
508         return cgRect;
509     }
510 #else
511     if (frameView && frameView->platformWidget()) {
512         NSRect nsRect = NSRectFromCGRect(cgRect);
513         NSView* view = frameView->documentView();
514         ALLOW_DEPRECATED_DECLARATIONS_BEGIN
515         nsRect = [[view window] convertRectToScreen:[view convertRect:nsRect toView:nil]];
516         ALLOW_DEPRECATED_DECLARATIONS_END
517         return NSRectToCGRect(nsRect);
518     }
519 #endif
520     else
521         return static_cast<CGRect>(m_object->convertFrameToSpace(rect, space));
522 }
523
524 - (NSString *)ariaLandmarkRoleDescription
525 {
526     switch (_axBackingObject->roleValue()) {
527     case AccessibilityRole::LandmarkBanner:
528         return AXARIAContentGroupText(@"ARIALandmarkBanner");
529     case AccessibilityRole::LandmarkComplementary:
530         return AXARIAContentGroupText(@"ARIALandmarkComplementary");
531     case AccessibilityRole::LandmarkContentInfo:
532         return AXARIAContentGroupText(@"ARIALandmarkContentInfo");
533     case AccessibilityRole::LandmarkMain:
534         return AXARIAContentGroupText(@"ARIALandmarkMain");
535     case AccessibilityRole::LandmarkNavigation:
536         return AXARIAContentGroupText(@"ARIALandmarkNavigation");
537     case AccessibilityRole::LandmarkDocRegion:
538     case AccessibilityRole::LandmarkRegion:
539         return AXARIAContentGroupText(@"ARIALandmarkRegion");
540     case AccessibilityRole::LandmarkSearch:
541         return AXARIAContentGroupText(@"ARIALandmarkSearch");
542     case AccessibilityRole::ApplicationAlert:
543         return AXARIAContentGroupText(@"ARIAApplicationAlert");
544     case AccessibilityRole::ApplicationAlertDialog:
545         return AXARIAContentGroupText(@"ARIAApplicationAlertDialog");
546     case AccessibilityRole::ApplicationDialog:
547         return AXARIAContentGroupText(@"ARIAApplicationDialog");
548     case AccessibilityRole::ApplicationLog:
549         return AXARIAContentGroupText(@"ARIAApplicationLog");
550     case AccessibilityRole::ApplicationMarquee:
551         return AXARIAContentGroupText(@"ARIAApplicationMarquee");
552     case AccessibilityRole::ApplicationStatus:
553         return AXARIAContentGroupText(@"ARIAApplicationStatus");
554     case AccessibilityRole::ApplicationTimer:
555         return AXARIAContentGroupText(@"ARIAApplicationTimer");
556     case AccessibilityRole::Document:
557         return AXARIAContentGroupText(@"ARIADocument");
558     case AccessibilityRole::DocumentArticle:
559         return AXARIAContentGroupText(@"ARIADocumentArticle");
560     case AccessibilityRole::DocumentMath:
561         return AXARIAContentGroupText(@"ARIADocumentMath");
562     case AccessibilityRole::DocumentNote:
563         return AXARIAContentGroupText(@"ARIADocumentNote");
564     case AccessibilityRole::UserInterfaceTooltip:
565         return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip");
566     case AccessibilityRole::TabPanel:
567         return AXARIAContentGroupText(@"ARIATabPanel");
568     case AccessibilityRole::WebApplication:
569         return AXARIAContentGroupText(@"ARIAWebApplication");
570     default:
571         return nil;
572     }
573 }
574
575 - (void)baseAccessibilitySetFocus:(BOOL)focus
576 {
577     // If focus is just set without making the view the first responder, then keyboard focus won't move to the right place.
578     if (focus && !m_object->document()->frame()->selection().isFocusedAndActive()) {
579         FrameView* frameView = m_object->documentFrameView();
580         Page* page = m_object->page();
581         if (page && frameView) {
582             ChromeClient& chromeClient = page->chrome().client();
583             chromeClient.focus();
584
585             // Legacy WebKit1 case.
586             if (frameView->platformWidget())
587                 chromeClient.makeFirstResponder(frameView->platformWidget());
588             else
589                 chromeClient.assistiveTechnologyMakeFirstResponder();
590         }
591     }
592
593     m_object->setFocused(focus);
594 }
595
596 - (NSString *)accessibilityPlatformMathSubscriptKey
597 {
598     ASSERT_NOT_REACHED();
599     return nil;
600 }
601
602 - (NSString *)accessibilityPlatformMathSuperscriptKey
603 {
604     ASSERT_NOT_REACHED();
605     return nil;    
606 }
607
608 - (NSArray *)accessibilityMathPostscriptPairs
609 {
610     AccessibilityObject::AccessibilityMathMultiscriptPairs pairs;
611     m_object->mathPostscripts(pairs);
612     return convertMathPairsToNSArray(pairs, [self accessibilityPlatformMathSubscriptKey], [self accessibilityPlatformMathSuperscriptKey]);
613 }
614
615 - (NSArray *)accessibilityMathPrescriptPairs
616 {
617     AccessibilityObject::AccessibilityMathMultiscriptPairs pairs;
618     m_object->mathPrescripts(pairs);
619     return convertMathPairsToNSArray(pairs, [self accessibilityPlatformMathSubscriptKey], [self accessibilityPlatformMathSuperscriptKey]);
620 }
621
622 // This is set by DRT when it wants to listen for notifications.
623 static BOOL accessibilityShouldRepostNotifications;
624 + (void)accessibilitySetShouldRepostNotifications:(BOOL)repost
625 {
626     accessibilityShouldRepostNotifications = repost;
627 #if PLATFORM(MAC)
628     AXObjectCache::setShouldRepostNotificationsForTests(repost);
629 #endif
630 }
631
632 - (void)accessibilityPostedNotification:(NSString *)notificationName
633 {
634     if (accessibilityShouldRepostNotifications)
635         [self accessibilityPostedNotification:notificationName userInfo:nil];
636 }
637
638 static bool isValueTypeSupported(id value)
639 {
640     return [value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSNumber class]] || [value isKindOfClass:[WebAccessibilityObjectWrapperBase class]];
641 }
642
643 static NSArray *arrayRemovingNonSupportedTypes(NSArray *array)
644 {
645     ASSERT([array isKindOfClass:[NSArray class]]);
646     NSMutableArray *mutableArray = [array mutableCopy];
647     for (NSUInteger i = 0; i < [mutableArray count];) {
648         id value = [mutableArray objectAtIndex:i];
649         if ([value isKindOfClass:[NSDictionary class]])
650             [mutableArray replaceObjectAtIndex:i withObject:dictionaryRemovingNonSupportedTypes(value)];
651         else if ([value isKindOfClass:[NSArray class]])
652             [mutableArray replaceObjectAtIndex:i withObject:arrayRemovingNonSupportedTypes(value)];
653         else if (!isValueTypeSupported(value)) {
654             [mutableArray removeObjectAtIndex:i];
655             continue;
656         }
657         i++;
658     }
659     return [mutableArray autorelease];
660 }
661
662 static NSDictionary *dictionaryRemovingNonSupportedTypes(NSDictionary *dictionary)
663 {
664     if (!dictionary)
665         return nil;
666     ASSERT([dictionary isKindOfClass:[NSDictionary class]]);
667     NSMutableDictionary *mutableDictionary = [dictionary mutableCopy];
668     for (NSString *key in dictionary) {
669         id value = [dictionary objectForKey:key];
670         if ([value isKindOfClass:[NSDictionary class]])
671             [mutableDictionary setObject:dictionaryRemovingNonSupportedTypes(value) forKey:key];
672         else if ([value isKindOfClass:[NSArray class]])
673             [mutableDictionary setObject:arrayRemovingNonSupportedTypes(value) forKey:key];
674         else if (!isValueTypeSupported(value))
675             [mutableDictionary removeObjectForKey:key];
676     }
677     return [mutableDictionary autorelease];
678 }
679
680 - (void)accessibilityPostedNotification:(NSString *)notificationName userInfo:(NSDictionary *)userInfo
681 {
682     if (accessibilityShouldRepostNotifications) {
683         ASSERT(notificationName);
684         userInfo = dictionaryRemovingNonSupportedTypes(userInfo);
685         NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:notificationName, @"notificationName", userInfo, @"userInfo", nil];
686         [[NSNotificationCenter defaultCenter] postNotificationName:@"AXDRTNotification" object:self userInfo:info];
687     }
688 }
689
690 #pragma mark Search helpers
691
692 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;
693
694 struct SearchKeyEntry {
695     String key;
696     AccessibilitySearchKey value;
697 };
698
699 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()
700 {
701     const SearchKeyEntry searchKeys[] = {
702         { NSAccessibilityAnyTypeSearchKey, AccessibilitySearchKey::AnyType },
703         { NSAccessibilityArticleSearchKey, AccessibilitySearchKey::Article },
704         { NSAccessibilityBlockquoteSameLevelSearchKey, AccessibilitySearchKey::BlockquoteSameLevel },
705         { NSAccessibilityBlockquoteSearchKey, AccessibilitySearchKey::Blockquote },
706         { NSAccessibilityBoldFontSearchKey, AccessibilitySearchKey::BoldFont },
707         { NSAccessibilityButtonSearchKey, AccessibilitySearchKey::Button },
708         { NSAccessibilityCheckBoxSearchKey, AccessibilitySearchKey::CheckBox },
709         { NSAccessibilityControlSearchKey, AccessibilitySearchKey::Control },
710         { NSAccessibilityDifferentTypeSearchKey, AccessibilitySearchKey::DifferentType },
711         { NSAccessibilityFontChangeSearchKey, AccessibilitySearchKey::FontChange },
712         { NSAccessibilityFontColorChangeSearchKey, AccessibilitySearchKey::FontColorChange },
713         { NSAccessibilityFrameSearchKey, AccessibilitySearchKey::Frame },
714         { NSAccessibilityGraphicSearchKey, AccessibilitySearchKey::Graphic },
715         { NSAccessibilityHeadingLevel1SearchKey, AccessibilitySearchKey::HeadingLevel1 },
716         { NSAccessibilityHeadingLevel2SearchKey, AccessibilitySearchKey::HeadingLevel2 },
717         { NSAccessibilityHeadingLevel3SearchKey, AccessibilitySearchKey::HeadingLevel3 },
718         { NSAccessibilityHeadingLevel4SearchKey, AccessibilitySearchKey::HeadingLevel4 },
719         { NSAccessibilityHeadingLevel5SearchKey, AccessibilitySearchKey::HeadingLevel5 },
720         { NSAccessibilityHeadingLevel6SearchKey, AccessibilitySearchKey::HeadingLevel6 },
721         { NSAccessibilityHeadingSameLevelSearchKey, AccessibilitySearchKey::HeadingSameLevel },
722         { NSAccessibilityHeadingSearchKey, AccessibilitySearchKey::Heading },
723         { NSAccessibilityHighlightedSearchKey, AccessibilitySearchKey::Highlighted },
724         { NSAccessibilityKeyboardFocusableSearchKey, AccessibilitySearchKey::KeyboardFocusable },
725         { NSAccessibilityItalicFontSearchKey, AccessibilitySearchKey::ItalicFont },
726         { NSAccessibilityLandmarkSearchKey, AccessibilitySearchKey::Landmark },
727         { NSAccessibilityLinkSearchKey, AccessibilitySearchKey::Link },
728         { NSAccessibilityListSearchKey, AccessibilitySearchKey::List },
729         { NSAccessibilityLiveRegionSearchKey, AccessibilitySearchKey::LiveRegion },
730         { NSAccessibilityMisspelledWordSearchKey, AccessibilitySearchKey::MisspelledWord },
731         { NSAccessibilityOutlineSearchKey, AccessibilitySearchKey::Outline },
732         { NSAccessibilityPlainTextSearchKey, AccessibilitySearchKey::PlainText },
733         { NSAccessibilityRadioGroupSearchKey, AccessibilitySearchKey::RadioGroup },
734         { NSAccessibilitySameTypeSearchKey, AccessibilitySearchKey::SameType },
735         { NSAccessibilityStaticTextSearchKey, AccessibilitySearchKey::StaticText },
736         { NSAccessibilityStyleChangeSearchKey, AccessibilitySearchKey::StyleChange },
737         { NSAccessibilityTableSameLevelSearchKey, AccessibilitySearchKey::TableSameLevel },
738         { NSAccessibilityTableSearchKey, AccessibilitySearchKey::Table },
739         { NSAccessibilityTextFieldSearchKey, AccessibilitySearchKey::TextField },
740         { NSAccessibilityUnderlineSearchKey, AccessibilitySearchKey::Underline },
741         { NSAccessibilityUnvisitedLinkSearchKey, AccessibilitySearchKey::UnvisitedLink },
742         { NSAccessibilityVisitedLinkSearchKey, AccessibilitySearchKey::VisitedLink }
743     };
744     
745     AccessibilitySearchKeyMap* searchKeyMap = new AccessibilitySearchKeyMap;
746     for (size_t i = 0; i < WTF_ARRAY_LENGTH(searchKeys); i++)
747         searchKeyMap->set(searchKeys[i].key, searchKeys[i].value);
748     
749     return searchKeyMap;
750 }
751
752 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)
753 {
754     if (value.isEmpty())
755         return AccessibilitySearchKey::AnyType;
756     
757     static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();
758     AccessibilitySearchKey searchKey = searchKeyMap->get(value);    
759     return static_cast<int>(searchKey) ? searchKey : AccessibilitySearchKey::AnyType;
760 }
761
762 AccessibilitySearchCriteria accessibilitySearchCriteriaForSearchPredicateParameterizedAttribute(const NSDictionary *parameterizedAttribute)
763 {
764     NSString *directionParameter = [parameterizedAttribute objectForKey:@"AXDirection"];
765     NSNumber *immediateDescendantsOnlyParameter = [parameterizedAttribute objectForKey:NSAccessibilityImmediateDescendantsOnly];
766     NSNumber *resultsLimitParameter = [parameterizedAttribute objectForKey:@"AXResultsLimit"];
767     NSString *searchTextParameter = [parameterizedAttribute objectForKey:@"AXSearchText"];
768     WebAccessibilityObjectWrapperBase *startElementParameter = [parameterizedAttribute objectForKey:@"AXStartElement"];
769     NSNumber *visibleOnlyParameter = [parameterizedAttribute objectForKey:@"AXVisibleOnly"];
770     id searchKeyParameter = [parameterizedAttribute objectForKey:@"AXSearchKey"];
771     
772     AccessibilitySearchDirection direction = AccessibilitySearchDirection::Next;
773     if ([directionParameter isKindOfClass:[NSString class]])
774         direction = [directionParameter isEqualToString:@"AXDirectionNext"] ? AccessibilitySearchDirection::Next : AccessibilitySearchDirection::Previous;
775     
776     bool immediateDescendantsOnly = false;
777     if ([immediateDescendantsOnlyParameter isKindOfClass:[NSNumber class]])
778         immediateDescendantsOnly = [immediateDescendantsOnlyParameter boolValue];
779     
780     unsigned resultsLimit = 0;
781     if ([resultsLimitParameter isKindOfClass:[NSNumber class]])
782         resultsLimit = [resultsLimitParameter unsignedIntValue];
783     
784     String searchText;
785     if ([searchTextParameter isKindOfClass:[NSString class]])
786         searchText = searchTextParameter;
787     
788     AccessibilityObject* startElement = nullptr;
789     if ([startElementParameter isKindOfClass:[WebAccessibilityObjectWrapperBase class]])
790         startElement = [startElementParameter accessibilityObject];
791     
792     bool visibleOnly = false;
793     if ([visibleOnlyParameter isKindOfClass:[NSNumber class]])
794         visibleOnly = [visibleOnlyParameter boolValue];
795     
796     AccessibilitySearchCriteria criteria = AccessibilitySearchCriteria(startElement, direction, searchText, resultsLimit, visibleOnly, immediateDescendantsOnly);
797     
798     if ([searchKeyParameter isKindOfClass:[NSString class]])
799         criteria.searchKeys.append(accessibilitySearchKeyForString(searchKeyParameter));
800     else if ([searchKeyParameter isKindOfClass:[NSArray class]]) {
801         size_t searchKeyCount = static_cast<size_t>([searchKeyParameter count]);
802         criteria.searchKeys.reserveInitialCapacity(searchKeyCount);
803         for (size_t i = 0; i < searchKeyCount; ++i) {
804             NSString *searchKey = [searchKeyParameter objectAtIndex:i];
805             if ([searchKey isKindOfClass:[NSString class]])
806                 criteria.searchKeys.uncheckedAppend(accessibilitySearchKeyForString(searchKey));
807         }
808     }
809     
810     return criteria;
811 }
812
813 @end
814
815 #endif // ENABLE(ACCESSIBILITY)