f3cc81d1ad8a3ed251eaa0e75de8b938977106a1
[WebKit-https.git] / Source / WebCore / accessibility / mac / WebAccessibilityObjectWrapper.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 Computer, 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 "WebAccessibilityObjectWrapper.h"
31
32 #if HAVE(ACCESSIBILITY)
33
34 #import "AXObjectCache.h"
35 #import "AccessibilityARIAGridRow.h"
36 #import "AccessibilityList.h"
37 #import "AccessibilityListBox.h"
38 #import "AccessibilityRenderObject.h"
39 #import "AccessibilityScrollView.h"
40 #import "AccessibilitySpinButton.h"
41 #import "AccessibilityTable.h"
42 #import "AccessibilityTableCell.h"
43 #import "AccessibilityTableColumn.h"
44 #import "AccessibilityTableRow.h"
45 #import "Chrome.h"
46 #import "ChromeClient.h"
47 #import "ColorMac.h"
48 #import "ContextMenuController.h"
49 #import "Font.h"
50 #import "Frame.h"
51 #import "FrameLoaderClient.h"
52 #import "FrameSelection.h"
53 #import "HTMLAnchorElement.h"
54 #import "HTMLAreaElement.h"
55 #import "HTMLFrameOwnerElement.h"
56 #import "HTMLImageElement.h"
57 #import "HTMLInputElement.h"
58 #import "HTMLNames.h"
59 #import "HTMLTextAreaElement.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 "SimpleFontData.h"
67 #import "TextCheckerClient.h"
68 #import "TextCheckingHelper.h"
69 #import "TextIterator.h"
70 #import "WebCoreFrameView.h"
71 #import "WebCoreObjCExtras.h"
72 #import "WebCoreSystemInterface.h"
73 #import "htmlediting.h"
74 #import "visible_units.h"
75
76 using namespace WebCore;
77 using namespace HTMLNames;
78 using namespace std;
79
80 // Cell Tables
81 #ifndef NSAccessibilitySelectedCellsAttribute
82 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"
83 #endif
84
85 #ifndef NSAccessibilityVisibleCellsAttribute
86 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"
87 #endif
88
89 #ifndef NSAccessibilityRowHeaderUIElementsAttribute
90 #define NSAccessibilityRowHeaderUIElementsAttribute @"AXRowHeaderUIElements"
91 #endif
92
93 #ifndef NSAccessibilityRowIndexRangeAttribute
94 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"
95 #endif
96
97 #ifndef NSAccessibilityColumnIndexRangeAttribute
98 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"
99 #endif
100
101 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute
102 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"
103 #endif
104
105 #ifndef NSAccessibilityCellRole
106 #define NSAccessibilityCellRole @"AXCell"
107 #endif
108
109 // Lists
110 #ifndef NSAccessibilityContentListSubrole
111 #define NSAccessibilityContentListSubrole @"AXContentList"
112 #endif
113
114 #ifndef NSAccessibilityDefinitionListSubrole
115 #define NSAccessibilityDefinitionListSubrole @"AXDefinitionList"
116 #endif
117
118 // Miscellaneous
119 #ifndef NSAccessibilityBlockQuoteLevelAttribute
120 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
121 #endif
122
123 #ifndef NSAccessibilityAccessKeyAttribute
124 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
125 #endif
126
127 #ifndef NSAccessibilityLanguageAttribute
128 #define NSAccessibilityLanguageAttribute @"AXLanguage"
129 #endif
130
131 #ifndef NSAccessibilityRequiredAttribute
132 #define NSAccessibilityRequiredAttribute @"AXRequired"
133 #endif
134
135 #ifndef NSAccessibilityInvalidAttribute
136 #define NSAccessibilityInvalidAttribute @"AXInvalid"
137 #endif
138
139 #ifndef NSAccessibilityOwnsAttribute
140 #define NSAccessibilityOwnsAttribute @"AXOwns"
141 #endif
142
143 #ifndef NSAccessibilityGrabbedAttribute
144 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
145 #endif
146
147 #ifndef NSAccessibilityDropEffectsAttribute
148 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
149 #endif
150
151 #ifndef NSAccessibilityARIALiveAttribute
152 #define NSAccessibilityARIALiveAttribute @"AXARIALive"
153 #endif
154
155 #ifndef NSAccessibilityARIAAtomicAttribute
156 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
157 #endif
158
159 #ifndef NSAccessibilityARIARelevantAttribute
160 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
161 #endif
162
163 #ifndef NSAccessibilityARIABusyAttribute
164 #define NSAccessibilityARIABusyAttribute @"AXARIABusy"
165 #endif
166
167 #ifndef NSAccessibilityLoadingProgressAttribute
168 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
169 #endif
170
171 #ifndef NSAccessibilityHasPopupAttribute
172 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"
173 #endif
174
175 #ifndef NSAccessibilityPlaceholderValueAttribute
176 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"
177 #endif
178
179 // Search
180 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute
181 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"
182 #endif
183
184 // Search Keys
185 #ifndef NSAccessibilityAnyTypeSearchKey
186 #define NSAccessibilityAnyTypeSearchKey @"AXAnyTypeSearchKey"
187 #endif
188
189 #ifndef NSAccessibilityBlockquoteSameLevelSearchKey
190 #define NSAccessibilityBlockquoteSameLevelSearchKey @"AXBlockquoteSameLevelSearchKey"
191 #endif
192
193 #ifndef NSAccessibilityBlockquoteSearchKey
194 #define NSAccessibilityBlockquoteSearchKey @"AXBlockquoteSearchKey"
195 #endif
196
197 #ifndef NSAccessibilityBoldFontSearchKey
198 #define NSAccessibilityBoldFontSearchKey @"AXBoldFontSearchKey"
199 #endif
200
201 #ifndef NSAccessibilityButtonSearchKey
202 #define NSAccessibilityButtonSearchKey @"AXButtonSearchKey"
203 #endif
204
205 #ifndef NSAccessibilityCheckBoxSearchKey
206 #define NSAccessibilityCheckBoxSearchKey @"AXCheckBoxSearchKey"
207 #endif
208
209 #ifndef NSAccessibilityControlSearchKey
210 #define NSAccessibilityControlSearchKey @"AXControlSearchKey"
211 #endif
212
213 #ifndef NSAccessibilityDifferentTypeSearchKey
214 #define NSAccessibilityDifferentTypeSearchKey @"AXDifferentTypeSearchKey"
215 #endif
216
217 #ifndef NSAccessibilityFontChangeSearchKey
218 #define NSAccessibilityFontChangeSearchKey @"AXFontChangeSearchKey"
219 #endif
220
221 #ifndef NSAccessibilityFontColorChangeSearchKey
222 #define NSAccessibilityFontColorChangeSearchKey @"AXFontColorChangeSearchKey"
223 #endif
224
225 #ifndef NSAccessibilityFrameSearchKey
226 #define NSAccessibilityFrameSearchKey @"AXFrameSearchKey"
227 #endif
228
229 #ifndef NSAccessibilityGraphicSearchKey
230 #define NSAccessibilityGraphicSearchKey @"AXGraphicSearchKey"
231 #endif
232
233 #ifndef NSAccessibilityHeadingLevel1SearchKey
234 #define NSAccessibilityHeadingLevel1SearchKey @"AXHeadingLevel1SearchKey"
235 #endif
236
237 #ifndef NSAccessibilityHeadingLevel2SearchKey
238 #define NSAccessibilityHeadingLevel2SearchKey @"AXHeadingLevel2SearchKey"
239 #endif
240
241 #ifndef NSAccessibilityHeadingLevel3SearchKey
242 #define NSAccessibilityHeadingLevel3SearchKey @"AXHeadingLevel3SearchKey"
243 #endif
244
245 #ifndef NSAccessibilityHeadingLevel4SearchKey
246 #define NSAccessibilityHeadingLevel4SearchKey @"AXHeadingLevel4SearchKey"
247 #endif
248
249 #ifndef NSAccessibilityHeadingLevel5SearchKey
250 #define NSAccessibilityHeadingLevel5SearchKey @"AXHeadingLevel5SearchKey"
251 #endif
252
253 #ifndef NSAccessibilityHeadingLevel6SearchKey
254 #define NSAccessibilityHeadingLevel6SearchKey @"AXHeadingLevel6SearchKey"
255 #endif
256
257 #ifndef NSAccessibilityHeadingSameLevelSearchKey
258 #define NSAccessibilityHeadingSameLevelSearchKey @"AXHeadingSameLevelSearchKey"
259 #endif
260
261 #ifndef NSAccessibilityHeadingSearchKey
262 #define NSAccessibilityHeadingSearchKey @"AXHeadingSearchKey"
263 #endif
264
265 #ifndef NSAccessibilityHighlightedSearchKey
266 #define NSAccessibilityHighlightedSearchKey @"AXHighlightedSearchKey"
267 #endif
268
269 #ifndef NSAccessibilityItalicFontSearchKey
270 #define NSAccessibilityItalicFontSearchKey @"AXItalicFontSearchKey"
271 #endif
272
273 #ifndef NSAccessibilityLandmarkSearchKey
274 #define NSAccessibilityLandmarkSearchKey @"AXLandmarkSearchKey"
275 #endif
276
277 #ifndef NSAccessibilityLinkSearchKey
278 #define NSAccessibilityLinkSearchKey @"AXLinkSearchKey"
279 #endif
280
281 #ifndef NSAccessibilityListSearchKey
282 #define NSAccessibilityListSearchKey @"AXListSearchKey"
283 #endif
284
285 #ifndef NSAccessibilityLiveRegionSearchKey
286 #define NSAccessibilityLiveRegionSearchKey @"AXLiveRegionSearchKey"
287 #endif
288
289 #ifndef NSAccessibilityMisspelledWordSearchKey
290 #define NSAccessibilityMisspelledWordSearchKey @"AXMisspelledWordSearchKey"
291 #endif
292
293 #ifndef NSAccessibilityPlainTextSearchKey
294 #define NSAccessibilityPlainTextSearchKey @"AXPlainTextSearchKey"
295 #endif
296
297 #ifndef NSAccessibilityRadioGroupSearchKey
298 #define NSAccessibilityRadioGroupSearchKey @"AXRadioGroupSearchKey"
299 #endif
300
301 #ifndef NSAccessibilitySameTypeSearchKey
302 #define NSAccessibilitySameTypeSearchKey @"AXSameTypeSearchKey"
303 #endif
304
305 #ifndef NSAccessibilityStaticTextSearchKey
306 #define NSAccessibilityStaticTextSearchKey @"AXStaticTextSearchKey"
307 #endif
308
309 #ifndef NSAccessibilityStyleChangeSearchKey
310 #define NSAccessibilityStyleChangeSearchKey @"AXStyleChangeSearchKey"
311 #endif
312
313 #ifndef NSAccessibilityTableSameLevelSearchKey
314 #define NSAccessibilityTableSameLevelSearchKey @"AXTableSameLevelSearchKey"
315 #endif
316
317 #ifndef NSAccessibilityTableSearchKey
318 #define NSAccessibilityTableSearchKey @"AXTableSearchKey"
319 #endif
320
321 #ifndef NSAccessibilityTextFieldSearchKey
322 #define NSAccessibilityTextFieldSearchKey @"AXTextFieldSearchKey"
323 #endif
324
325 #ifndef NSAccessibilityUnderlineSearchKey
326 #define NSAccessibilityUnderlineSearchKey @"AXUnderlineSearchKey"
327 #endif
328
329 #ifndef NSAccessibilityUnvisitedLinkSearchKey
330 #define NSAccessibilityUnvisitedLinkSearchKey @"AXUnvisitedLinkSearchKey"
331 #endif
332
333 #ifndef NSAccessibilityVisitedLinkSearchKey
334 #define NSAccessibilityVisitedLinkSearchKey @"AXVisitedLinkSearchKey"
335 #endif
336
337 #define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
338 #define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
339 #define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
340
341 // Math attributes
342 #define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
343 #define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"
344 #define NSAccessibilityMathFractionDenominatorAttribute @"AXMathFractionDenominator"
345 #define NSAccessibilityMathFractionNumeratorAttribute @"AXMathFractionNumerator"
346 #define NSAccessibilityMathBaseAttribute @"AXMathBase"
347 #define NSAccessibilityMathSubscriptAttribute @"AXMathSubscript"
348 #define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
349 #define NSAccessibilityMathUnderAttribute @"AXMathUnder"
350 #define NSAccessibilityMathOverAttribute @"AXMathOver"
351 #define NSAccessibilityMathFencedOpenAttribute @"AXMathFencedOpen"
352 #define NSAccessibilityMathFencedCloseAttribute @"AXMathFencedClose"
353
354 @interface NSObject (WebKitAccessibilityArrayCategory)
355
356 - (NSUInteger)accessibilityIndexOfChild:(id)child;
357 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
358 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
359
360 @end
361
362 @implementation WebAccessibilityObjectWrapper
363
364 - (id)initWithAccessibilityObject:(AccessibilityObject*)axObject
365 {
366     if (!(self = [super init]))
367         return nil;
368
369     m_object = axObject;
370     return self;
371 }
372
373 - (void)unregisterUniqueIdForUIElement
374 {
375     wkUnregisterUniqueIdForElement(self);
376 }
377
378 - (void)detach
379 {
380     // Send unregisterUniqueIdForUIElement unconditionally because if it is
381     // ever accidentally not done (via other bugs in our AX implementation) you
382     // end up with a crash like <rdar://problem/4273149>.  It is safe and not
383     // expensive to send even if the object is not registered.
384     [self unregisterUniqueIdForUIElement];
385     m_object = 0;
386 }
387
388 - (BOOL)updateObjectBackingStore
389 {
390     // Calling updateBackingStore() can invalidate this element so self must be retained.
391     // If it does become invalidated, m_object will be nil.
392     [[self retain] autorelease];
393     
394     if (!m_object)
395         return NO;
396     
397     m_object->updateBackingStore();
398     if (!m_object)
399         return NO;
400     
401     return YES;
402 }
403
404 - (AccessibilityObject*)accessibilityObject
405 {
406     return m_object;
407 }
408
409 - (NSView*)attachmentView
410 {
411     ASSERT(m_object->isAttachment());
412     Widget* widget = m_object->widgetForAttachmentView();
413     if (!widget)
414         return nil;
415     return NSAccessibilityUnignoredDescendant(widget->platformWidget());
416 }
417
418 #pragma mark SystemInterface wrappers
419
420 static inline id CFAutoreleaseHelper(CFTypeRef obj)
421 {
422     if (obj)
423         CFMakeCollectable(obj);
424     [(id)obj autorelease];
425     return (id)obj;
426 }
427
428 static inline BOOL AXObjectIsTextMarker(id obj)
429 {
430     return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerTypeID();    
431 }
432
433 static inline BOOL AXObjectIsTextMarkerRange(id obj)
434 {
435     return obj != nil && CFGetTypeID(obj) == wkGetAXTextMarkerRangeTypeID();    
436 }
437
438 static id AXTextMarkerRange(id startMarker, id endMarker)
439 {
440     ASSERT(startMarker != nil);
441     ASSERT(endMarker != nil);
442     ASSERT(CFGetTypeID(startMarker) == wkGetAXTextMarkerTypeID());
443     ASSERT(CFGetTypeID(endMarker) == wkGetAXTextMarkerTypeID());
444     return CFAutoreleaseHelper(wkCreateAXTextMarkerRange((CFTypeRef)startMarker, (CFTypeRef)endMarker));
445 }
446
447 static id AXTextMarkerRangeStart(id range)
448 {
449     ASSERT(range != nil);
450     ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
451     return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeStart(range));    
452 }
453
454 static id AXTextMarkerRangeEnd(id range)
455 {
456     ASSERT(range != nil);
457     ASSERT(CFGetTypeID(range) == wkGetAXTextMarkerRangeTypeID());
458     return CFAutoreleaseHelper(wkCopyAXTextMarkerRangeEnd(range));    
459 }
460
461 #pragma mark Search helpers
462
463 typedef HashMap<String, AccessibilitySearchKey> AccessibilitySearchKeyMap;
464
465 struct SearchKeyEntry {
466     String key;
467     AccessibilitySearchKey value;
468 };
469
470 static AccessibilitySearchKeyMap* createAccessibilitySearchKeyMap()
471 {
472     const SearchKeyEntry searchKeys[] = {
473         { NSAccessibilityAnyTypeSearchKey, AnyTypeSearchKey },
474         { NSAccessibilityBlockquoteSameLevelSearchKey, BlockquoteSameLevelSearchKey },
475         { NSAccessibilityBlockquoteSearchKey, BlockquoteSearchKey },
476         { NSAccessibilityBoldFontSearchKey, BoldFontSearchKey },
477         { NSAccessibilityButtonSearchKey, ButtonSearchKey },
478         { NSAccessibilityCheckBoxSearchKey, CheckBoxSearchKey },
479         { NSAccessibilityControlSearchKey, ControlSearchKey },
480         { NSAccessibilityDifferentTypeSearchKey, DifferentTypeSearchKey },
481         { NSAccessibilityFontChangeSearchKey, FontChangeSearchKey },
482         { NSAccessibilityFontColorChangeSearchKey, FontColorChangeSearchKey },
483         { NSAccessibilityFrameSearchKey, FrameSearchKey },
484         { NSAccessibilityGraphicSearchKey, GraphicSearchKey },
485         { NSAccessibilityHeadingLevel1SearchKey, HeadingLevel1SearchKey },
486         { NSAccessibilityHeadingLevel2SearchKey, HeadingLevel2SearchKey },
487         { NSAccessibilityHeadingLevel3SearchKey, HeadingLevel3SearchKey },
488         { NSAccessibilityHeadingLevel4SearchKey, HeadingLevel4SearchKey },
489         { NSAccessibilityHeadingLevel5SearchKey, HeadingLevel5SearchKey },
490         { NSAccessibilityHeadingLevel6SearchKey, HeadingLevel6SearchKey },
491         { NSAccessibilityHeadingSameLevelSearchKey, HeadingSameLevelSearchKey },
492         { NSAccessibilityHeadingSearchKey, HeadingSearchKey },
493         { NSAccessibilityHighlightedSearchKey, HighlightedSearchKey },
494         { NSAccessibilityItalicFontSearchKey, ItalicFontSearchKey },
495         { NSAccessibilityLandmarkSearchKey, LandmarkSearchKey },
496         { NSAccessibilityLinkSearchKey, LinkSearchKey },
497         { NSAccessibilityListSearchKey, ListSearchKey },
498         { NSAccessibilityLiveRegionSearchKey, LiveRegionSearchKey },
499         { NSAccessibilityMisspelledWordSearchKey, MisspelledWordSearchKey },
500         { NSAccessibilityPlainTextSearchKey, PlainTextSearchKey },
501         { NSAccessibilityRadioGroupSearchKey, RadioGroupSearchKey },
502         { NSAccessibilitySameTypeSearchKey, SameTypeSearchKey },
503         { NSAccessibilityStaticTextSearchKey, StaticTextSearchKey },
504         { NSAccessibilityStyleChangeSearchKey, StyleChangeSearchKey },
505         { NSAccessibilityTableSameLevelSearchKey, TableSameLevelSearchKey },
506         { NSAccessibilityTableSearchKey, TableSearchKey },
507         { NSAccessibilityTextFieldSearchKey, TextFieldSearchKey },
508         { NSAccessibilityUnderlineSearchKey, UnderlineSearchKey },
509         { NSAccessibilityUnvisitedLinkSearchKey, UnvisitedLinkSearchKey },
510         { NSAccessibilityVisitedLinkSearchKey, VisitedLinkSearchKey }
511     };
512     
513     AccessibilitySearchKeyMap* searchKeyMap = new AccessibilitySearchKeyMap;
514     for (size_t i = 0; i < WTF_ARRAY_LENGTH(searchKeys); i++)
515         searchKeyMap->set(searchKeys[i].key, searchKeys[i].value);
516     
517     return searchKeyMap;
518 }
519
520 static AccessibilitySearchKey accessibilitySearchKeyForString(const String& value)
521 {
522     if (value.isEmpty())
523         return AnyTypeSearchKey;
524     
525     static const AccessibilitySearchKeyMap* searchKeyMap = createAccessibilitySearchKeyMap();
526     
527     AccessibilitySearchKey searchKey = searchKeyMap->get(value);
528     
529     return searchKey ? searchKey : AnyTypeSearchKey;
530 }
531
532 #pragma mark Text Marker helpers
533
534 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
535 {
536     ASSERT(cache);
537     
538     TextMarkerData textMarkerData;
539     cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
540     if (!textMarkerData.axID)
541         return nil;
542     
543     return CFAutoreleaseHelper(wkCreateAXTextMarker(&textMarkerData, sizeof(textMarkerData)));
544 }
545
546 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
547 {
548     return textMarkerForVisiblePosition(m_object->axObjectCache(), visiblePos);
549 }
550
551 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
552 {
553     ASSERT(cache);
554
555     if (!textMarker)
556         return VisiblePosition();
557     TextMarkerData textMarkerData;
558     if (!wkGetBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
559         return VisiblePosition();
560     
561     return cache->visiblePositionForTextMarkerData(textMarkerData);
562 }
563
564 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
565 {
566     return visiblePositionForTextMarker(m_object->axObjectCache(), textMarker);
567 }
568
569 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
570 {
571     return visiblePositionForTextMarker(cache, AXTextMarkerRangeStart(textMarkerRange));
572 }
573
574 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache *cache, id textMarkerRange)
575 {
576     return visiblePositionForTextMarker(cache, AXTextMarkerRangeEnd(textMarkerRange));
577 }
578
579 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
580 {
581     if (!textMarker1 || !textMarker2)
582         return nil;
583         
584     return AXTextMarkerRange(textMarker1, textMarker2);
585 }
586
587 // When modifying attributed strings, the range can come from a source which may provide faulty information (e.g. the spell checker).
588 // To protect against such cases the range should be validated before adding or removing attributes.
589 static BOOL AXAttributedStringRangeIsValid(NSAttributedString* attrString, NSRange range)
590 {
591     return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);
592 }
593
594 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, NSString* attribute, NSFont* font, NSRange range)
595 {
596     if (!AXAttributedStringRangeIsValid(attrString, range))
597         return;
598     
599     if (font) {
600         NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
601             [font fontName]                             , NSAccessibilityFontNameKey,
602             [font familyName]                           , NSAccessibilityFontFamilyKey,
603             [font displayName]                          , NSAccessibilityVisibleNameKey,
604             [NSNumber numberWithFloat:[font pointSize]] , NSAccessibilityFontSizeKey,
605         nil];
606
607         [attrString addAttribute:attribute value:dict range:range];
608     } else
609         [attrString removeAttribute:attribute range:range];
610     
611 }
612
613 static CGColorRef CreateCGColorIfDifferent(NSColor* nsColor, CGColorRef existingColor)
614 {
615     // get color information assuming NSDeviceRGBColorSpace 
616     NSColor* rgbColor = [nsColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
617     if (rgbColor == nil)
618         rgbColor = [NSColor blackColor];
619     CGFloat components[4];
620     [rgbColor getRed:&components[0] green:&components[1] blue:&components[2] alpha:&components[3]];
621     
622     // create a new CGColorRef to return
623     CGColorSpaceRef cgColorSpace = CGColorSpaceCreateDeviceRGB();
624     CGColorRef cgColor = CGColorCreate(cgColorSpace, components);
625     CGColorSpaceRelease(cgColorSpace);
626     
627     // check for match with existing color
628     if (existingColor && CGColorEqualToColor(cgColor, existingColor)) {
629         CGColorRelease(cgColor);
630         cgColor = 0;
631     }
632     
633     return cgColor;
634 }
635
636 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
637 {
638     if (!AXAttributedStringRangeIsValid(attrString, range))
639         return;
640
641     if (color) {
642         CGColorRef existingColor = (CGColorRef) [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
643         CGColorRef cgColor = CreateCGColorIfDifferent(color, existingColor);
644         if (cgColor) {
645             [attrString addAttribute:attribute value:(id)cgColor range:range];
646             CGColorRelease(cgColor);
647         }
648     } else
649         [attrString removeAttribute:attribute range:range];
650 }
651
652 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
653 {
654     if (!AXAttributedStringRangeIsValid(attrString, range))
655         return;
656
657     if (number)
658         [attrString addAttribute:attribute value:number range:range];
659     else
660         [attrString removeAttribute:attribute range:range];
661 }
662
663 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
664 {
665     RenderStyle* style = renderer->style();
666
667     // set basic font info
668     AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style->font().primaryFont()->getNSFont(), range);
669
670     // set basic colors
671     AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyColor)), range);
672     AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style->visitedDependentColor(CSSPropertyBackgroundColor)), range);
673
674     // set super/sub scripting
675     EVerticalAlign alignment = style->verticalAlign();
676     if (alignment == SUB)
677         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
678     else if (alignment == SUPER)
679         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
680     else
681         [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
682     
683     // set shadow
684     if (style->textShadow())
685         AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, [NSNumber numberWithBool:YES], range);
686     else
687         [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
688     
689     // set underline and strikethrough
690     int decor = style->textDecorationsInEffect();
691     if ((decor & UNDERLINE) == 0) {
692         [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
693         [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
694     }
695     
696     if ((decor & LINE_THROUGH) == 0) {
697         [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
698         [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
699     }
700
701     if ((decor & (UNDERLINE | LINE_THROUGH)) != 0) {
702         // find colors using quirk mode approach (strict mode would use current
703         // color for all but the root line box, which would use getTextDecorationColors)
704         Color underline, overline, linethrough;
705         renderer->getTextDecorationColors(decor, underline, overline, linethrough);
706         
707         if ((decor & UNDERLINE) != 0) {
708             AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, [NSNumber numberWithBool:YES], range);
709             AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(underline), range);
710         }
711
712         if ((decor & LINE_THROUGH) != 0) {
713             AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, [NSNumber numberWithBool:YES], range);
714             AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(linethrough), range);
715         }
716     }
717     
718     // Indicate background highlighting.
719     for (Node* node = renderer->node(); node; node = node->parentNode()) {
720         if (node->hasTagName(markTag))
721             AXAttributeStringSetNumber(attrString, @"AXHighlight", [NSNumber numberWithBool:YES], range);
722     }
723 }
724
725 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
726 {
727     if (!AXAttributedStringRangeIsValid(attrString, range))
728         return;
729
730     AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
731     int quoteLevel = obj->blockquoteLevel();
732     
733     if (quoteLevel)
734         [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
735     else
736         [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
737 }
738
739 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int charLength, NSRange range)
740 {
741     if (unifiedTextCheckerEnabled(node->document()->frame())) {
742         // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.
743         TextCheckerClient* checker = node->document()->frame()->editor()->textChecker();
744
745         // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
746         Vector<TextCheckingResult> results;
747         checkTextOfParagraph(checker, chars, charLength, TextCheckingTypeSpelling, results);
748
749         size_t size = results.size();
750         NSNumber* trueValue = [NSNumber numberWithBool:YES];
751         for (unsigned i = 0; i < size; i++) {
752             const TextCheckingResult& result = results[i];
753             AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, trueValue, NSMakeRange(result.location + range.location, result.length));
754         }
755         return;
756     }
757
758     int currentPosition = 0;
759     while (charLength > 0) {
760         const UChar* charData = chars + currentPosition;
761         TextCheckerClient* checker = node->document()->frame()->editor()->textChecker();
762         
763         int misspellingLocation = -1;
764         int misspellingLength = 0;
765         checker->checkSpellingOfString(charData, charLength, &misspellingLocation, &misspellingLength);
766         if (misspellingLocation == -1 || !misspellingLength)
767             break;
768         
769         NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);
770         AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, [NSNumber numberWithBool:YES], spellRange);
771         charLength -= (misspellingLocation + misspellingLength);
772         currentPosition += (misspellingLocation + misspellingLength);
773     }
774 }
775
776 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
777 {
778     if (!renderer)
779         return;
780     
781     if (!AXAttributedStringRangeIsValid(attrString, range))
782         return;
783     
784     // Sometimes there are objects between the text and the heading. 
785     // In those cases the parent hierarchy should be queried to see if there is a heading level.
786     int parentHeadingLevel = 0;
787     AccessibilityObject* parentObject = renderer->document()->axObjectCache()->getOrCreate(renderer->parent());
788     for (; parentObject; parentObject = parentObject->parentObject()) {
789         parentHeadingLevel = parentObject->headingLevel();
790         if (parentHeadingLevel)
791             break;
792     }
793     
794     if (parentHeadingLevel)
795         [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
796     else
797         [attrString removeAttribute:@"AXHeadingLevel" range:range];
798 }
799
800 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
801 {
802     if (!AXAttributedStringRangeIsValid(attrString, range))
803         return;
804
805     if (object && object->isAccessibilityRenderObject()) {
806         // make a serializable AX object
807         
808         RenderObject* renderer = static_cast<AccessibilityRenderObject*>(object)->renderer();
809         if (!renderer)
810             return;
811         
812         Document* doc = renderer->document();
813         if (!doc)
814             return;
815         
816         AXObjectCache* cache = doc->axObjectCache();
817         if (!cache)
818             return;
819
820         AXUIElementRef axElement = wkCreateAXUIElementRef(object->wrapper());
821         if (axElement) {
822             [attrString addAttribute:attribute value:(id)axElement range:range];
823             CFRelease(axElement);
824         }
825     } else
826         [attrString removeAttribute:attribute range:range];
827 }
828
829 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, const UChar* chars, int length)
830 {
831     // skip invisible text
832     if (!node->renderer())
833         return;
834
835     // easier to calculate the range before appending the string
836     NSRange attrStringRange = NSMakeRange([attrString length], length);
837     
838     // append the string from this node
839     [[attrString mutableString] appendString:[NSString stringWithCharacters:chars length:length]];
840
841     // add new attributes and remove irrelevant inherited ones
842     // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
843     // identical colors.  Workaround is to not replace an existing color attribute if it matches what we are adding.  This also means
844     // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
845
846     // remove inherited attachment from prior AXAttributedStringAppendReplaced
847     [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
848     [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
849     
850     // set new attributes
851     AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange);
852     AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange);
853     AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange);
854     AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
855     
856     // do spelling last because it tends to break up the range
857     AXAttributeStringSetSpelling(attrString, node, chars, length, attrStringRange);
858 }
859
860 static NSString* nsStringForReplacedNode(Node* replacedNode)
861 {
862     // we should always be given a rendered node and a replaced node, but be safe
863     // replaced nodes are either attachments (widgets) or images
864     if (!replacedNode || !replacedNode->renderer() || !replacedNode->renderer()->isReplaced() || replacedNode->isTextNode()) {
865         ASSERT_NOT_REACHED();
866         return nil;
867     }
868
869     // create an AX object, but skip it if it is not supposed to be seen
870     RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
871     if (obj->accessibilityIsIgnored())
872         return nil;
873     
874     // use the attachmentCharacter to represent the replaced node
875     const UniChar attachmentChar = NSAttachmentCharacter;
876     return [NSString stringWithCharacters:&attachmentChar length:1];
877 }
878
879 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange
880 {
881     if (!m_object)
882         return nil;
883     
884     // extract the start and end VisiblePosition
885     VisiblePosition startVisiblePosition = visiblePositionForStartOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
886     if (startVisiblePosition.isNull())
887         return nil;
888
889     VisiblePosition endVisiblePosition = visiblePositionForEndOfTextMarkerRange(m_object->axObjectCache(), textMarkerRange);
890     if (endVisiblePosition.isNull())
891         return nil;
892
893     VisiblePositionRange visiblePositionRange(startVisiblePosition, endVisiblePosition);
894     // iterate over the range to build the AX attributed string
895     NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
896     TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
897     while (!it.atEnd()) {
898         // locate the node and starting offset for this range
899         int exception = 0;
900         Node* node = it.range()->startContainer(exception);
901         ASSERT(node == it.range()->endContainer(exception));
902         int offset = it.range()->startOffset(exception);
903
904         // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
905         if (it.length() != 0) {
906             // Add the text of the list marker item if necessary.
907             String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition()));
908             if (!listMarkerText.isEmpty())
909                 AXAttributedStringAppendText(attrString, node, listMarkerText.characters(), listMarkerText.length());
910             
911             AXAttributedStringAppendText(attrString, node, it.characters(), it.length());
912         } else {
913             Node* replacedNode = node->childNode(offset);
914             NSString *attachmentString = nsStringForReplacedNode(replacedNode);
915             if (attachmentString) {
916                 NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
917
918                 // append the placeholder string
919                 [[attrString mutableString] appendString:attachmentString];
920
921                 // remove all inherited attributes
922                 [attrString setAttributes:nil range:attrStringRange];
923
924                 // add the attachment attribute
925                 AccessibilityObject* obj = replacedNode->renderer()->document()->axObjectCache()->getOrCreate(replacedNode->renderer());
926                 AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
927             }
928         }
929         it.advance();
930     }
931
932     return [attrString autorelease];
933 }
934
935 static id textMarkerRangeFromVisiblePositions(AXObjectCache *cache, VisiblePosition startPosition, VisiblePosition endPosition)
936 {
937     id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
938     id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
939     return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
940 }
941
942 - (id)textMarkerRangeFromVisiblePositions:(VisiblePosition)startPosition endPosition:(VisiblePosition)endPosition
943 {
944     return textMarkerRangeFromVisiblePositions(m_object->axObjectCache(), startPosition, endPosition);
945 }
946
947 - (NSArray*)accessibilityActionNames
948 {
949     if (![self updateObjectBackingStore])
950         return nil;
951
952     static NSArray* actionElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityPressAction, NSAccessibilityShowMenuAction, nil];
953     static NSArray* defaultElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityShowMenuAction, nil];
954     static NSArray* menuElementActions = [[NSArray alloc] initWithObjects: NSAccessibilityCancelAction, NSAccessibilityPressAction, nil];
955     static NSArray* sliderActions = [[NSArray alloc] initWithObjects: NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil];
956
957     NSArray *actions;
958     if (m_object->actionElement() || m_object->isButton()) 
959         actions = actionElementActions;
960     else if (m_object->isMenuRelated())
961         actions = menuElementActions;
962     else if (m_object->isSlider())
963         actions = sliderActions;
964     else if (m_object->isAttachment())
965         actions = [[self attachmentView] accessibilityActionNames];
966     else
967         actions = defaultElementActions;
968
969     return actions;
970 }
971
972 - (NSArray*)additionalAccessibilityAttributeNames
973 {
974     if (!m_object)
975         return nil;
976
977     NSMutableArray *additional = [NSMutableArray array];
978     if (m_object->supportsARIAOwns())
979         [additional addObject:NSAccessibilityOwnsAttribute];
980
981     if (m_object->supportsARIAExpanded())
982         [additional addObject:NSAccessibilityExpandedAttribute];
983     
984     if (m_object->isScrollbar())
985         [additional addObject:NSAccessibilityOrientationAttribute];
986     
987     if (m_object->supportsARIADragging())
988         [additional addObject:NSAccessibilityGrabbedAttribute];
989
990     if (m_object->supportsARIADropping())
991         [additional addObject:NSAccessibilityDropEffectsAttribute];
992
993     if (m_object->isAccessibilityTable() && static_cast<AccessibilityTable*>(m_object)->supportsSelectedRows())
994         [additional addObject:NSAccessibilitySelectedRowsAttribute];        
995     
996     if (m_object->supportsARIALiveRegion()) {
997         [additional addObject:NSAccessibilityARIALiveAttribute];
998         [additional addObject:NSAccessibilityARIARelevantAttribute];
999     }
1000     
1001     if (m_object->sortDirection() != SortDirectionNone)
1002         [additional addObject:NSAccessibilitySortDirectionAttribute];
1003         
1004     // If an object is a child of a live region, then add these
1005     if (m_object->isInsideARIALiveRegion())
1006         [additional addObject:NSAccessibilityARIAAtomicAttribute];
1007     // All objects should expose the ARIA busy attribute (ARIA 1.1 with ISSUE-538).
1008     [additional addObject:NSAccessibilityARIABusyAttribute];
1009     
1010     // Popup buttons on the Mac expose the value attribute.
1011     if (m_object->isPopUpButton())
1012         [additional addObject:NSAccessibilityValueAttribute];
1013
1014     if (m_object->ariaHasPopup())
1015         [additional addObject:NSAccessibilityHasPopupAttribute];
1016     
1017     if (m_object->isMathRoot()) {
1018         // The index of a square root is always known, so there's no object associated with it.
1019         if (!m_object->isMathSquareRoot())
1020             [additional addObject:NSAccessibilityMathRootIndexAttribute];
1021         [additional addObject:NSAccessibilityMathRootRadicandAttribute];
1022     } else if (m_object->isMathFraction()) {
1023         [additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
1024         [additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
1025     } else if (m_object->isMathSubscriptSuperscript()) {
1026         [additional addObject:NSAccessibilityMathBaseAttribute];
1027         [additional addObject:NSAccessibilityMathSubscriptAttribute];
1028         [additional addObject:NSAccessibilityMathSuperscriptAttribute];
1029     } else if (m_object->isMathUnderOver()) {
1030         [additional addObject:NSAccessibilityMathBaseAttribute];
1031         [additional addObject:NSAccessibilityMathUnderAttribute];
1032         [additional addObject:NSAccessibilityMathOverAttribute];
1033     } else if (m_object->isMathFenced()) {
1034         [additional addObject:NSAccessibilityMathFencedOpenAttribute];
1035         [additional addObject:NSAccessibilityMathFencedCloseAttribute];
1036     }
1037
1038     return additional;
1039 }
1040
1041 - (NSArray*)accessibilityAttributeNames
1042 {
1043     if (![self updateObjectBackingStore])
1044         return nil;
1045     
1046     if (m_object->isAttachment())
1047         return [[self attachmentView] accessibilityAttributeNames];
1048
1049     static NSArray* attributes = nil;
1050     static NSArray* anchorAttrs = nil;
1051     static NSArray* webAreaAttrs = nil;
1052     static NSArray* textAttrs = nil;
1053     static NSArray* listAttrs = nil;
1054     static NSArray* listBoxAttrs = nil;
1055     static NSArray* rangeAttrs = nil;
1056     static NSArray* commonMenuAttrs = nil;
1057     static NSArray* menuAttrs = nil;
1058     static NSArray* menuBarAttrs = nil;
1059     static NSArray* menuItemAttrs = nil;
1060     static NSArray* menuButtonAttrs = nil;
1061     static NSArray* controlAttrs = nil;
1062     static NSArray* tableAttrs = nil;
1063     static NSArray* tableRowAttrs = nil;
1064     static NSArray* tableColAttrs = nil;
1065     static NSArray* tableCellAttrs = nil;
1066     static NSArray* groupAttrs = nil;
1067     static NSArray* inputImageAttrs = nil;
1068     static NSArray* passwordFieldAttrs = nil;
1069     static NSArray* tabListAttrs = nil;
1070     static NSArray* comboBoxAttrs = nil;
1071     static NSArray* outlineAttrs = nil;
1072     static NSArray* outlineRowAttrs = nil;
1073     static NSArray* buttonAttrs = nil;
1074     static NSArray* scrollViewAttrs = nil;
1075     static NSArray* incrementorAttrs = nil;
1076     NSMutableArray* tempArray;
1077     if (attributes == nil) {
1078         attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1079                       NSAccessibilitySubroleAttribute,
1080                       NSAccessibilityRoleDescriptionAttribute,
1081                       NSAccessibilityChildrenAttribute,
1082                       NSAccessibilityHelpAttribute,
1083                       NSAccessibilityParentAttribute,
1084                       NSAccessibilityPositionAttribute,
1085                       NSAccessibilitySizeAttribute,
1086                       NSAccessibilityTitleAttribute,
1087                       NSAccessibilityDescriptionAttribute,
1088                       NSAccessibilityValueAttribute,
1089                       NSAccessibilityFocusedAttribute,
1090                       NSAccessibilityEnabledAttribute,
1091                       NSAccessibilityWindowAttribute,
1092                       @"AXSelectedTextMarkerRange",
1093                       @"AXStartTextMarker",
1094                       @"AXEndTextMarker",
1095                       @"AXVisited",
1096                       NSAccessibilityLinkedUIElementsAttribute,
1097                       NSAccessibilitySelectedAttribute,
1098                       NSAccessibilityBlockQuoteLevelAttribute,
1099                       NSAccessibilityTopLevelUIElementAttribute,
1100                       nil];
1101     }
1102     if (commonMenuAttrs == nil) {
1103         commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1104                             NSAccessibilityRoleDescriptionAttribute,
1105                             NSAccessibilityChildrenAttribute,
1106                             NSAccessibilityParentAttribute,
1107                             NSAccessibilityEnabledAttribute,
1108                             NSAccessibilityPositionAttribute,
1109                             NSAccessibilitySizeAttribute,
1110                             nil];
1111     }
1112     if (anchorAttrs == nil) {
1113         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1114         [tempArray addObject:NSAccessibilityURLAttribute];
1115         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1116         anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1117         [tempArray release];
1118     }
1119     if (webAreaAttrs == nil) {
1120         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1121         [tempArray addObject:@"AXLinkUIElements"];
1122         [tempArray addObject:@"AXLoaded"];
1123         [tempArray addObject:@"AXLayoutCount"];
1124         [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1125         [tempArray addObject:NSAccessibilityURLAttribute];
1126         webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1127         [tempArray release];
1128     }
1129     if (textAttrs == nil) {
1130         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1131         [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1132         [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1133         [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1134         [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1135         [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1136         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1137         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1138         [tempArray addObject:NSAccessibilityRequiredAttribute];
1139         [tempArray addObject:NSAccessibilityInvalidAttribute];
1140         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1141         textAttrs = [[NSArray alloc] initWithArray:tempArray];
1142         [tempArray release];
1143     }
1144     if (listAttrs == nil) {
1145         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1146         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1147         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1148         [tempArray addObject:NSAccessibilityOrientationAttribute];
1149         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1150         listAttrs = [[NSArray alloc] initWithArray:tempArray];
1151         [tempArray release];
1152     }
1153     if (listBoxAttrs == nil) {
1154         tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];    
1155         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1156         [tempArray addObject:NSAccessibilityRequiredAttribute];
1157         [tempArray addObject:NSAccessibilityInvalidAttribute];
1158         listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1159         [tempArray release];
1160     }
1161     if (rangeAttrs == nil) {
1162         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1163         [tempArray addObject:NSAccessibilityMinValueAttribute];
1164         [tempArray addObject:NSAccessibilityMaxValueAttribute];
1165         [tempArray addObject:NSAccessibilityOrientationAttribute];
1166         [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1167         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1168         rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1169         [tempArray release];
1170     }
1171     if (menuBarAttrs == nil) {
1172         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1173         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1174         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1175         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1176         menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1177         [tempArray release];
1178     }
1179     if (menuAttrs == nil) {
1180         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1181         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1182         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1183         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1184         menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1185         [tempArray release];
1186     }
1187     if (menuItemAttrs == nil) {
1188         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1189         [tempArray addObject:NSAccessibilityTitleAttribute];
1190         [tempArray addObject:NSAccessibilityHelpAttribute];
1191         [tempArray addObject:NSAccessibilitySelectedAttribute];
1192         [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1193         [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1194         [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1195         [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1196         [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1197         [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1198         [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1199         menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1200         [tempArray release];
1201     }
1202     if (menuButtonAttrs == nil) {
1203         menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1204             NSAccessibilityRoleDescriptionAttribute,
1205             NSAccessibilityParentAttribute,
1206             NSAccessibilityPositionAttribute,
1207             NSAccessibilitySizeAttribute,
1208             NSAccessibilityWindowAttribute,
1209             NSAccessibilityEnabledAttribute,
1210             NSAccessibilityFocusedAttribute,
1211             NSAccessibilityTitleAttribute,
1212             NSAccessibilityChildrenAttribute, nil];
1213     }
1214     if (controlAttrs == nil) {
1215         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1216         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1217         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1218         [tempArray addObject:NSAccessibilityRequiredAttribute];
1219         [tempArray addObject:NSAccessibilityInvalidAttribute];
1220         controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1221         [tempArray release];
1222     }
1223     if (incrementorAttrs == nil) {
1224         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1225         [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1226         [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1227         incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1228         [tempArray release];
1229     }
1230     if (buttonAttrs == nil) {
1231         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1232         // Buttons should not expose AXValue.
1233         [tempArray removeObject:NSAccessibilityValueAttribute];
1234         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1235         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1236         buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1237         [tempArray release];
1238     }
1239     if (comboBoxAttrs == nil) {
1240         tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1241         [tempArray addObject:NSAccessibilityExpandedAttribute];
1242         comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1243         [tempArray release];        
1244     }
1245     if (tableAttrs == nil) {
1246         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1247         [tempArray addObject:NSAccessibilityRowsAttribute];
1248         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1249         [tempArray addObject:NSAccessibilityColumnsAttribute];
1250         [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1251         [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1252         [tempArray addObject:(NSString *)kAXColumnHeaderUIElementsAttribute];
1253         [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1254         [tempArray addObject:NSAccessibilityHeaderAttribute];
1255         tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1256         [tempArray release];
1257     }
1258     if (tableRowAttrs == nil) {
1259         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1260         [tempArray addObject:NSAccessibilityIndexAttribute];
1261         tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1262         [tempArray release];
1263     }
1264     if (tableColAttrs == nil) {
1265         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1266         [tempArray addObject:NSAccessibilityIndexAttribute];
1267         [tempArray addObject:NSAccessibilityHeaderAttribute];
1268         [tempArray addObject:NSAccessibilityRowsAttribute];
1269         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1270         tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1271         [tempArray release];
1272     }
1273     if (tableCellAttrs == nil) {
1274         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1275         [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1276         [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1277         tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1278         [tempArray release];        
1279     }
1280     if (groupAttrs == nil) {
1281         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1282         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1283         groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1284         [tempArray release];
1285     }
1286     if (inputImageAttrs == nil) {
1287         tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1288         [tempArray addObject:NSAccessibilityURLAttribute];
1289         inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1290         [tempArray release];
1291     }
1292     if (passwordFieldAttrs == nil) {
1293         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1294         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1295         [tempArray addObject:NSAccessibilityRequiredAttribute];
1296         [tempArray addObject:NSAccessibilityInvalidAttribute];
1297         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1298         passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1299         [tempArray release];
1300     }
1301     if (tabListAttrs == nil) {
1302         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1303         [tempArray addObject:NSAccessibilityTabsAttribute];
1304         [tempArray addObject:NSAccessibilityContentsAttribute];
1305         tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1306         [tempArray release];        
1307     }
1308     if (outlineAttrs == nil) {
1309         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1310         [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1311         [tempArray addObject:NSAccessibilityRowsAttribute];
1312         [tempArray addObject:NSAccessibilityColumnsAttribute];
1313         outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1314         [tempArray release];
1315     }
1316     if (outlineRowAttrs == nil) {
1317         tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1318         [tempArray addObject:NSAccessibilityDisclosingAttribute];
1319         [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1320         [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1321         [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1322         outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1323         [tempArray release];
1324     }
1325     if (scrollViewAttrs == nil) {
1326         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1327         [tempArray addObject:NSAccessibilityContentsAttribute];
1328         [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1329         [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1330         scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1331         [tempArray release];
1332     }
1333     
1334     NSArray *objectAttributes = attributes;
1335     
1336     if (m_object->isPasswordField())
1337         objectAttributes = passwordFieldAttrs;
1338
1339     else if (m_object->isWebArea())
1340         objectAttributes = webAreaAttrs;
1341     
1342     else if (m_object->isTextControl())
1343         objectAttributes = textAttrs;
1344
1345     else if (m_object->isAnchor() || m_object->isImage() || m_object->isLink())
1346         objectAttributes = anchorAttrs;
1347
1348     else if (m_object->isAccessibilityTable())
1349         objectAttributes = tableAttrs;
1350     else if (m_object->isTableColumn())
1351         objectAttributes = tableColAttrs;
1352     else if (m_object->isTableCell())
1353         objectAttributes = tableCellAttrs;
1354     else if (m_object->isTableRow()) {
1355         // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1356         if (m_object->isARIATreeGridRow())
1357             objectAttributes = outlineRowAttrs;
1358         else
1359             objectAttributes = tableRowAttrs;
1360     }
1361     
1362     else if (m_object->isTree())
1363         objectAttributes = outlineAttrs;
1364     else if (m_object->isTreeItem())
1365         objectAttributes = outlineRowAttrs;
1366     
1367     else if (m_object->isListBox())
1368         objectAttributes = listBoxAttrs;
1369     else if (m_object->isList())
1370         objectAttributes = listAttrs;
1371     
1372     else if (m_object->isComboBox())
1373         objectAttributes = comboBoxAttrs;
1374     
1375     else if (m_object->isProgressIndicator() || m_object->isSlider())
1376         objectAttributes = rangeAttrs;
1377
1378     // These are processed in order because an input image is a button, and a button is a control.
1379     else if (m_object->isInputImage())
1380         objectAttributes = inputImageAttrs;
1381     else if (m_object->isButton())
1382         objectAttributes = buttonAttrs;
1383     else if (m_object->isControl())
1384         objectAttributes = controlAttrs;
1385     
1386     else if (m_object->isGroup() || m_object->isListItem())
1387         objectAttributes = groupAttrs;
1388     else if (m_object->isTabList())
1389         objectAttributes = tabListAttrs;
1390     else if (m_object->isScrollView())
1391         objectAttributes = scrollViewAttrs;
1392     else if (m_object->isSpinButton())
1393         objectAttributes = incrementorAttrs;
1394     
1395     else if (m_object->isMenu())
1396         objectAttributes = menuAttrs;
1397     else if (m_object->isMenuBar())
1398         objectAttributes = menuBarAttrs;
1399     else if (m_object->isMenuButton())
1400         objectAttributes = menuButtonAttrs;
1401     else if (m_object->isMenuItem())
1402         objectAttributes = menuItemAttrs;
1403     
1404     NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1405     if ([additionalAttributes count])
1406         objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1407     
1408     return objectAttributes;
1409 }
1410
1411 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1412 {
1413     if (!textMarkerRange)
1414         return VisiblePositionRange();
1415     AXObjectCache* cache = m_object->axObjectCache();
1416     return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1417 }
1418
1419 - (NSArray*)renderWidgetChildren
1420 {
1421     Widget* widget = m_object->widget();
1422     if (!widget)
1423         return nil;
1424     return [(widget->platformWidget()) accessibilityAttributeValue: NSAccessibilityChildrenAttribute];
1425 }
1426
1427 - (id)remoteAccessibilityParentObject
1428 {
1429     if (!m_object)
1430         return nil;
1431     
1432     Document* document = m_object->document();
1433     if (!document)
1434         return nil;
1435     
1436     Frame* frame = document->frame();
1437     if (!frame)
1438         return nil;
1439     
1440     return frame->loader()->client()->accessibilityRemoteObject();
1441 }
1442
1443 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1444 {
1445     unsigned length = [array count];
1446     vector.reserveInitialCapacity(length);
1447     for (unsigned i = 0; i < length; ++i) {
1448         AccessibilityObject* obj = [[array objectAtIndex:i] accessibilityObject];
1449         if (obj)
1450             vector.append(obj);
1451     }
1452 }
1453
1454 static NSMutableArray* convertToNSArray(const AccessibilityObject::AccessibilityChildrenVector& vector)
1455 {
1456     unsigned length = vector.size();
1457     NSMutableArray* array = [NSMutableArray arrayWithCapacity: length];
1458     for (unsigned i = 0; i < length; ++i) {
1459         WebAccessibilityObjectWrapper* wrapper = vector[i]->wrapper();
1460         ASSERT(wrapper);
1461         if (wrapper) {
1462             // we want to return the attachment view instead of the object representing the attachment.
1463             // otherwise, we get palindrome errors in the AX hierarchy
1464             if (vector[i]->isAttachment() && [wrapper attachmentView])
1465                 [array addObject:[wrapper attachmentView]];
1466             else
1467                 [array addObject:wrapper];
1468         }
1469     }
1470     return array;
1471 }
1472
1473 - (id)textMarkerRangeForSelection
1474 {
1475     VisibleSelection selection = m_object->selection();
1476     if (selection.isNone())
1477         return nil;
1478     return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1479 }
1480
1481 - (NSValue *)position
1482 {
1483     IntRect rect = pixelSnappedIntRect(m_object->elementRect());
1484     NSPoint point;
1485     
1486     FrameView* frameView = m_object->documentFrameView();
1487
1488     // WebKit1 code path... platformWidget() exists.
1489     if (frameView && frameView->platformWidget()) {
1490     
1491         // The Cocoa accessibility API wants the lower-left corner.
1492         point = NSMakePoint(rect.x(), rect.maxY());
1493         
1494         if (frameView) {
1495             NSView* view = frameView->documentView();
1496             point = [[view window] convertBaseToScreen:[view convertPoint: point toView:nil]];
1497         }
1498     } else {
1499         
1500         // Find the appropriate scroll view to use to convert the contents to the window.
1501         ScrollView* scrollView = 0;
1502         AccessibilityObject* parent = 0;
1503         for (parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1504             if (parent->isAccessibilityScrollView()) {
1505                 scrollView = toAccessibilityScrollView(parent)->scrollView();
1506                 break;
1507             }
1508         }
1509
1510         if (scrollView)
1511             rect = scrollView->contentsToRootView(rect);
1512         
1513         Page* page = m_object->page();
1514         
1515         // If we have an empty chrome client (like SVG) then we should use the page
1516         // of the scroll view parent to help us get to the screen rect.
1517         if (parent && page && page->chrome()->client()->isEmptyChromeClient())
1518             page = parent->page();
1519
1520         if (page)
1521             point = page->chrome()->rootViewToScreen(rect).location();
1522         else
1523             point = rect.location();
1524     }
1525     
1526     return [NSValue valueWithPoint:point];
1527 }
1528
1529 typedef HashMap<int, NSString*> AccessibilityRoleMap;
1530
1531 static const AccessibilityRoleMap& createAccessibilityRoleMap()
1532 {
1533     struct RoleEntry {
1534         AccessibilityRole value;
1535         NSString* string;
1536     };
1537     
1538     static const RoleEntry roles[] = {
1539         { UnknownRole, NSAccessibilityUnknownRole },
1540         { ButtonRole, NSAccessibilityButtonRole },
1541         { RadioButtonRole, NSAccessibilityRadioButtonRole },
1542         { CheckBoxRole, NSAccessibilityCheckBoxRole },
1543         { SliderRole, NSAccessibilitySliderRole },
1544         { TabGroupRole, NSAccessibilityTabGroupRole },
1545         { TextFieldRole, NSAccessibilityTextFieldRole },
1546         { StaticTextRole, NSAccessibilityStaticTextRole },
1547         { TextAreaRole, NSAccessibilityTextAreaRole },
1548         { ScrollAreaRole, NSAccessibilityScrollAreaRole },
1549         { PopUpButtonRole, NSAccessibilityPopUpButtonRole },
1550         { MenuButtonRole, NSAccessibilityMenuButtonRole },
1551         { TableRole, NSAccessibilityTableRole },
1552         { ApplicationRole, NSAccessibilityApplicationRole },
1553         { GroupRole, NSAccessibilityGroupRole },
1554         { RadioGroupRole, NSAccessibilityRadioGroupRole },
1555         { ListRole, NSAccessibilityListRole },
1556         { DirectoryRole, NSAccessibilityListRole },
1557         { ScrollBarRole, NSAccessibilityScrollBarRole },
1558         { ValueIndicatorRole, NSAccessibilityValueIndicatorRole },
1559         { ImageRole, NSAccessibilityImageRole },
1560         { MenuBarRole, NSAccessibilityMenuBarRole },
1561         { MenuRole, NSAccessibilityMenuRole },
1562         { MenuItemRole, NSAccessibilityMenuItemRole },
1563         { ColumnRole, NSAccessibilityColumnRole },
1564         { RowRole, NSAccessibilityRowRole },
1565         { ToolbarRole, NSAccessibilityToolbarRole },
1566         { BusyIndicatorRole, NSAccessibilityBusyIndicatorRole },
1567         { ProgressIndicatorRole, NSAccessibilityProgressIndicatorRole },
1568         { WindowRole, NSAccessibilityWindowRole },
1569         { DrawerRole, NSAccessibilityDrawerRole },
1570         { SystemWideRole, NSAccessibilitySystemWideRole },
1571         { OutlineRole, NSAccessibilityOutlineRole },
1572         { IncrementorRole, NSAccessibilityIncrementorRole },
1573         { BrowserRole, NSAccessibilityBrowserRole },
1574         { ComboBoxRole, NSAccessibilityComboBoxRole },
1575         { SplitGroupRole, NSAccessibilitySplitGroupRole },
1576         { SplitterRole, NSAccessibilitySplitterRole },
1577         { ColorWellRole, NSAccessibilityColorWellRole },
1578         { GrowAreaRole, NSAccessibilityGrowAreaRole },
1579         { SheetRole, NSAccessibilitySheetRole },
1580         { HelpTagRole, NSAccessibilityHelpTagRole },
1581         { MatteRole, NSAccessibilityMatteRole }, 
1582         { RulerRole, NSAccessibilityRulerRole },
1583         { RulerMarkerRole, NSAccessibilityRulerMarkerRole },
1584         { LinkRole, NSAccessibilityLinkRole },
1585         { DisclosureTriangleRole, NSAccessibilityDisclosureTriangleRole },
1586         { GridRole, NSAccessibilityGridRole },
1587         { WebCoreLinkRole, NSAccessibilityLinkRole }, 
1588         { ImageMapLinkRole, NSAccessibilityLinkRole },
1589         { ImageMapRole, @"AXImageMap" },
1590         { ListMarkerRole, @"AXListMarker" },
1591         { WebAreaRole, @"AXWebArea" },
1592         { SeamlessWebAreaRole, NSAccessibilityGroupRole },
1593         { HeadingRole, @"AXHeading" },
1594         { ListBoxRole, NSAccessibilityListRole },
1595         { ListBoxOptionRole, NSAccessibilityStaticTextRole },
1596 #if ACCESSIBILITY_TABLES
1597         { CellRole, NSAccessibilityCellRole },
1598 #else
1599         { CellRole, NSAccessibilityGroupRole },
1600 #endif
1601         { TableHeaderContainerRole, NSAccessibilityGroupRole },
1602         { RowHeaderRole, NSAccessibilityGroupRole },
1603         { DefinitionListDefinitionRole, NSAccessibilityGroupRole },
1604         { DefinitionListTermRole, NSAccessibilityGroupRole },
1605         { SliderThumbRole, NSAccessibilityValueIndicatorRole },
1606         { LandmarkApplicationRole, NSAccessibilityGroupRole },
1607         { LandmarkBannerRole, NSAccessibilityGroupRole },
1608         { LandmarkComplementaryRole, NSAccessibilityGroupRole },
1609         { LandmarkContentInfoRole, NSAccessibilityGroupRole },
1610         { LandmarkMainRole, NSAccessibilityGroupRole },
1611         { LandmarkNavigationRole, NSAccessibilityGroupRole },
1612         { LandmarkSearchRole, NSAccessibilityGroupRole },
1613         { ApplicationAlertRole, NSAccessibilityGroupRole },
1614         { ApplicationAlertDialogRole, NSAccessibilityGroupRole },
1615         { ApplicationDialogRole, NSAccessibilityGroupRole },
1616         { ApplicationLogRole, NSAccessibilityGroupRole },
1617         { ApplicationMarqueeRole, NSAccessibilityGroupRole },
1618         { ApplicationStatusRole, NSAccessibilityGroupRole },
1619         { ApplicationTimerRole, NSAccessibilityGroupRole },
1620         { DocumentRole, NSAccessibilityGroupRole },
1621         { DocumentArticleRole, NSAccessibilityGroupRole },
1622         { DocumentMathRole, NSAccessibilityGroupRole },
1623         { DocumentNoteRole, NSAccessibilityGroupRole },
1624         { DocumentRegionRole, NSAccessibilityGroupRole },
1625         { UserInterfaceTooltipRole, NSAccessibilityGroupRole },
1626         { TabRole, NSAccessibilityRadioButtonRole },
1627         { TabListRole, NSAccessibilityTabGroupRole },
1628         { TabPanelRole, NSAccessibilityGroupRole },
1629         { TreeRole, NSAccessibilityOutlineRole },
1630         { TreeItemRole, NSAccessibilityRowRole },
1631         { ListItemRole, NSAccessibilityGroupRole },
1632         { ParagraphRole, NSAccessibilityGroupRole },
1633         { LabelRole, NSAccessibilityGroupRole },
1634         { DivRole, NSAccessibilityGroupRole },
1635         { FormRole, NSAccessibilityGroupRole },
1636         { SpinButtonRole, NSAccessibilityIncrementorRole },
1637         { FooterRole, NSAccessibilityGroupRole },
1638         { ToggleButtonRole, NSAccessibilityButtonRole },
1639         { CanvasRole, NSAccessibilityImageRole },
1640         { SVGRootRole, NSAccessibilityGroupRole },
1641         { LegendRole, NSAccessibilityGroupRole },
1642         { MathElementRole, NSAccessibilityGroupRole }
1643     };
1644     AccessibilityRoleMap& roleMap = *new AccessibilityRoleMap;
1645     
1646     const unsigned numRoles = sizeof(roles) / sizeof(roles[0]);
1647     for (unsigned i = 0; i < numRoles; ++i)
1648         roleMap.set(roles[i].value, roles[i].string);
1649     return roleMap;
1650 }
1651
1652 static NSString* roleValueToNSString(AccessibilityRole value)
1653 {
1654     ASSERT(value);
1655     static const AccessibilityRoleMap& roleMap = createAccessibilityRoleMap();
1656     return roleMap.get(value);
1657 }
1658
1659 - (NSString*)role
1660 {
1661     if (m_object->isAttachment())
1662         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
1663     AccessibilityRole role = m_object->roleValue();
1664     if (role == CanvasRole && m_object->canvasHasFallbackContent())
1665         role = GroupRole;
1666     NSString* string = roleValueToNSString(role);
1667     if (string != nil)
1668         return string;
1669     return NSAccessibilityUnknownRole;
1670 }
1671
1672 - (NSString*)subrole
1673 {
1674     if (m_object->isPasswordField())
1675         return NSAccessibilitySecureTextFieldSubrole;
1676     if (m_object->isSearchField())
1677         return NSAccessibilitySearchFieldSubrole;
1678     
1679     if (m_object->isAttachment()) {
1680         NSView* attachView = [self attachmentView];
1681         if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute]) {
1682             return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
1683         }
1684     }
1685     
1686     if (m_object->isSpinButtonPart()) {
1687         if (toAccessibilitySpinButtonPart(m_object)->isIncrementor())
1688             return NSAccessibilityIncrementArrowSubrole;
1689
1690         return NSAccessibilityDecrementArrowSubrole;
1691     }
1692     
1693     if (m_object->isFileUploadButton())
1694         return @"AXFileUploadButton";
1695     
1696     if (m_object->isTreeItem())
1697         return NSAccessibilityOutlineRowSubrole;
1698     
1699     if (m_object->isList()) {
1700         AccessibilityList* listObject = static_cast<AccessibilityList*>(m_object);
1701         if (listObject->isUnorderedList() || listObject->isOrderedList())
1702             return NSAccessibilityContentListSubrole;
1703         if (listObject->isDefinitionList())
1704             return NSAccessibilityDefinitionListSubrole;
1705     }
1706     
1707     // ARIA content subroles.
1708     switch (m_object->roleValue()) {
1709         case LandmarkApplicationRole:
1710             return @"AXLandmarkApplication";
1711         case LandmarkBannerRole:
1712             return @"AXLandmarkBanner";
1713         case LandmarkComplementaryRole:
1714             return @"AXLandmarkComplementary";
1715         // Footer roles should appear as content info types.
1716         case FooterRole:
1717         case LandmarkContentInfoRole:
1718             return @"AXLandmarkContentInfo";
1719         case LandmarkMainRole:
1720             return @"AXLandmarkMain";
1721         case LandmarkNavigationRole:
1722             return @"AXLandmarkNavigation";
1723         case LandmarkSearchRole:
1724             return @"AXLandmarkSearch";
1725         case ApplicationAlertRole:
1726             return @"AXApplicationAlert";
1727         case ApplicationAlertDialogRole:
1728             return @"AXApplicationAlertDialog";
1729         case ApplicationDialogRole:
1730             return @"AXApplicationDialog";
1731         case ApplicationLogRole:
1732             return @"AXApplicationLog";
1733         case ApplicationMarqueeRole:
1734             return @"AXApplicationMarquee";
1735         case ApplicationStatusRole:
1736             return @"AXApplicationStatus";
1737         case ApplicationTimerRole:
1738             return @"AXApplicationTimer";
1739         case DocumentRole:
1740             return @"AXDocument";
1741         case DocumentArticleRole:
1742             return @"AXDocumentArticle";
1743         case DocumentMathRole:
1744             return @"AXDocumentMath";
1745         case DocumentNoteRole:
1746             return @"AXDocumentNote";
1747         case DocumentRegionRole:
1748             return @"AXDocumentRegion";
1749         case UserInterfaceTooltipRole:
1750             return @"AXUserInterfaceTooltip";
1751         case TabPanelRole:
1752             return @"AXTabPanel";
1753         case DefinitionListTermRole:
1754             return @"AXTerm";
1755         case DefinitionListDefinitionRole:
1756             return @"AXDefinition";
1757         // Default doesn't return anything, so roles defined below can be chosen.
1758         default:
1759             break;
1760     }
1761     
1762     if (m_object->roleValue() == MathElementRole) {
1763         if (m_object->isMathFraction())
1764             return @"AXMathFraction";
1765         if (m_object->isMathFenced())
1766             return @"AXMathFenced";
1767         if (m_object->isMathSubscriptSuperscript())
1768             return @"AXMathSubscriptSuperscript";
1769         if (m_object->isMathRow())
1770             return @"AXMathRow";
1771         if (m_object->isMathUnderOver())
1772             return @"AXMathUnderOver";
1773         if (m_object->isMathSquareRoot())
1774             return @"AXMathSquareRoot";
1775         if (m_object->isMathRoot())
1776             return @"AXMathRoot";
1777         if (m_object->isMathText())
1778             return @"AXMathText";
1779         if (m_object->isMathNumber())
1780             return @"AXMathNumber";
1781         if (m_object->isMathIdentifier())
1782             return @"AXMathIdentifier";
1783         if (m_object->isMathTable())
1784             return @"AXMathTable";
1785         if (m_object->isMathTableRow())
1786             return @"AXMathTableRow";
1787         if (m_object->isMathTableCell())
1788             return @"AXMathTableCell";
1789         if (m_object->isMathFenceOperator())
1790             return @"AXMathFenceOperator";
1791         if (m_object->isMathSeparatorOperator())
1792             return @"AXMathSeparatorOperator";
1793         if (m_object->isMathOperator())
1794             return @"AXMathOperator";
1795     }
1796     
1797     if (m_object->isMediaTimeline())
1798         return NSAccessibilityTimelineSubrole;
1799
1800     return nil;
1801 }
1802
1803 - (NSString*)roleDescription
1804 {
1805     if (!m_object)
1806         return nil;
1807
1808     // attachments have the AXImage role, but a different subrole
1809     if (m_object->isAttachment())
1810         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
1811     
1812     NSString* axRole = [self role];
1813     
1814     if ([axRole isEqualToString:NSAccessibilityGroupRole]) {
1815         switch (m_object->roleValue()) {
1816             default:
1817                 return NSAccessibilityRoleDescription(NSAccessibilityGroupRole, [self subrole]);
1818             case LandmarkApplicationRole:
1819                 return AXARIAContentGroupText(@"ARIALandmarkApplication");
1820             case LandmarkBannerRole:
1821                 return AXARIAContentGroupText(@"ARIALandmarkBanner");
1822             case LandmarkComplementaryRole:
1823                 return AXARIAContentGroupText(@"ARIALandmarkComplementary");
1824             case LandmarkContentInfoRole:
1825                 return AXARIAContentGroupText(@"ARIALandmarkContentInfo");
1826             case LandmarkMainRole:
1827                 return AXARIAContentGroupText(@"ARIALandmarkMain");
1828             case LandmarkNavigationRole:
1829                 return AXARIAContentGroupText(@"ARIALandmarkNavigation");
1830             case LandmarkSearchRole:
1831                 return AXARIAContentGroupText(@"ARIALandmarkSearch");
1832             case ApplicationAlertRole:
1833                 return AXARIAContentGroupText(@"ARIAApplicationAlert");
1834             case ApplicationAlertDialogRole:
1835                 return AXARIAContentGroupText(@"ARIAApplicationAlertDialog");
1836             case ApplicationDialogRole:
1837                 return AXARIAContentGroupText(@"ARIAApplicationDialog");
1838             case ApplicationLogRole:
1839                 return AXARIAContentGroupText(@"ARIAApplicationLog");
1840             case ApplicationMarqueeRole:
1841                 return AXARIAContentGroupText(@"ARIAApplicationMarquee");
1842             case ApplicationStatusRole:
1843                 return AXARIAContentGroupText(@"ARIAApplicationStatus");
1844             case ApplicationTimerRole:
1845                 return AXARIAContentGroupText(@"ARIAApplicationTimer");
1846             case DocumentRole:
1847                 return AXARIAContentGroupText(@"ARIADocument");
1848             case DocumentArticleRole:
1849                 return AXARIAContentGroupText(@"ARIADocumentArticle");
1850             case DocumentMathRole:
1851                 return AXARIAContentGroupText(@"ARIADocumentMath");
1852             case DocumentNoteRole:
1853                 return AXARIAContentGroupText(@"ARIADocumentNote");
1854             case DocumentRegionRole:
1855                 return AXARIAContentGroupText(@"ARIADocumentRegion");
1856             case UserInterfaceTooltipRole:
1857                 return AXARIAContentGroupText(@"ARIAUserInterfaceTooltip");
1858             case TabPanelRole:
1859                 return AXARIAContentGroupText(@"ARIATabPanel");
1860             case DefinitionListTermRole:
1861                 return AXDefinitionListTermText();
1862             case DefinitionListDefinitionRole:
1863                 return AXDefinitionListDefinitionText();
1864             case FooterRole:
1865                 return AXFooterRoleDescriptionText();
1866         }
1867     }        
1868     
1869     if ([axRole isEqualToString:@"AXWebArea"])
1870         return AXWebAreaText();
1871     
1872     if ([axRole isEqualToString:@"AXLink"])
1873         return AXLinkText();
1874     
1875     if ([axRole isEqualToString:@"AXListMarker"])
1876         return AXListMarkerText();
1877     
1878     if ([axRole isEqualToString:@"AXImageMap"])
1879         return AXImageMapText();
1880
1881     if ([axRole isEqualToString:@"AXHeading"])
1882         return AXHeadingText();
1883
1884     if (m_object->isFileUploadButton())
1885         return AXFileUploadButtonText();
1886     
1887     // AppKit also returns AXTab for the role description for a tab item.
1888     if (m_object->isTabItem())
1889         return NSAccessibilityRoleDescription(@"AXTab", nil);
1890     
1891     // We should try the system default role description for all other roles.
1892     // If we get the same string back, then as a last resort, return unknown.
1893     NSString* defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
1894     if (![defaultRoleDescription isEqualToString:axRole])
1895         return defaultRoleDescription;
1896
1897     return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
1898 }
1899
1900 - (id)scrollViewParent
1901 {
1902     if (!m_object || !m_object->isAccessibilityScrollView())
1903         return nil;
1904     
1905     // If this scroll view provides it's parent object (because it's a sub-frame), then
1906     // we should not find the remoteAccessibilityParent.
1907     if (m_object->parentObject())
1908         return nil;
1909     
1910     AccessibilityScrollView* scrollView = toAccessibilityScrollView(m_object);
1911     ScrollView* scroll = scrollView->scrollView();
1912     if (!scroll)
1913         return nil;
1914     
1915     if (scroll->platformWidget())
1916         return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
1917
1918     return [self remoteAccessibilityParentObject];
1919 }
1920
1921 // FIXME: Different kinds of elements are putting the title tag to use in different
1922 // AX fields. This should be rectified, but in the initial patch I want to achieve
1923 // parity with existing behavior.
1924 - (BOOL)titleTagShouldBeUsedInDescriptionField
1925 {
1926     return (m_object->isLink() && !m_object->isImageMapLink()) || m_object->isImage();
1927 }
1928
1929 // This should be the "visible" text that's actually on the screen if possible.
1930 // If there's alternative text, that can override the title.
1931 - (NSString *)accessibilityTitle
1932 {
1933     // Static text objects should not have a title. Its content is communicated in its AXValue.
1934     if (m_object->roleValue() == StaticTextRole)
1935         return [NSString string];
1936
1937     // A file upload button presents a challenge because it has button text and a value, but the
1938     // API doesn't support this paradigm.
1939     // The compromise is to return the button type in the role description and the value of the file path in the title
1940     if (m_object->isFileUploadButton())
1941         return m_object->stringValue();
1942     
1943     Vector<AccessibilityText> textOrder;
1944     m_object->accessibilityText(textOrder);
1945     
1946     unsigned length = textOrder.size();
1947     for (unsigned k = 0; k < length; k++) {
1948         const AccessibilityText& text = textOrder[k];
1949         
1950         // If we have alternative text, then we should not expose a title.
1951         if (text.textSource == AlternativeText)
1952             break;
1953         
1954         // Once we encounter visible text, or the text from our children that should be used foremost.
1955         if (text.textSource == VisibleText || text.textSource == ChildrenText)
1956             return text.text;
1957         
1958         // If there's an element that labels this object and it's not exposed, then we should use
1959         // that text as our title.
1960         if (text.textSource == LabelByElementText && !m_object->exposesTitleUIElement())
1961             return text.text;
1962         
1963         // FIXME: The title tag is used in certain cases for the title. This usage should
1964         // probably be in the description field since it's not "visible".
1965         if (text.textSource == TitleTagText && ![self titleTagShouldBeUsedInDescriptionField])
1966             return text.text;
1967     }
1968     
1969     return [NSString string];
1970 }
1971
1972 - (NSString *)accessibilityDescription
1973 {
1974     // Static text objects should not have a description. Its content is communicated in its AXValue.
1975     // One exception is the media control labels that have a value and a description. Those are set programatically.
1976     if (m_object->roleValue() == StaticTextRole && !m_object->isMediaControlLabel())
1977         return [NSString string];
1978     
1979     Vector<AccessibilityText> textOrder;
1980     m_object->accessibilityText(textOrder);
1981     
1982     unsigned length = textOrder.size();
1983     for (unsigned k = 0; k < length; k++) {
1984         const AccessibilityText& text = textOrder[k];
1985         
1986         if (text.textSource == AlternativeText)
1987             return text.text;
1988         
1989         if (text.textSource == TitleTagText && [self titleTagShouldBeUsedInDescriptionField])
1990             return text.text;
1991     }
1992     
1993     return [NSString string];
1994 }
1995
1996 - (NSString *)accessibilityHelpText
1997 {
1998     Vector<AccessibilityText> textOrder;
1999     m_object->accessibilityText(textOrder);
2000     
2001     unsigned length = textOrder.size();
2002     bool descriptiveTextAvailable = false;
2003     for (unsigned k = 0; k < length; k++) {
2004         const AccessibilityText& text = textOrder[k];
2005         
2006         if (text.textSource == HelpText || text.textSource == SummaryText)
2007             return text.text;
2008         
2009         // If an element does NOT have other descriptive text the title tag should be used as its descriptive text.
2010         // But, if those ARE available, then the title tag should be used for help text instead.
2011         switch (text.textSource) {
2012         case AlternativeText:
2013         case VisibleText:
2014         case ChildrenText:
2015         case LabelByElementText:
2016             descriptiveTextAvailable = true;
2017         default:
2018             break;
2019         }
2020         
2021         if (text.textSource == TitleTagText && descriptiveTextAvailable)
2022             return text.text;
2023     }
2024     
2025     return [NSString string];
2026 }
2027
2028 // FIXME: split up this function in a better way.  
2029 // suggestions: Use a hash table that maps attribute names to function calls,
2030 // or maybe pointers to member functions
2031 - (id)accessibilityAttributeValue:(NSString*)attributeName
2032 {
2033     if (![self updateObjectBackingStore])
2034         return nil;
2035     
2036     if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
2037         return [self role];
2038
2039     if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
2040         return [self subrole];
2041
2042     if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
2043         return [self roleDescription];
2044
2045     if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
2046
2047         // This will return the parent of the AXWebArea, if this is a web area.
2048         id scrollViewParent = [self scrollViewParent];
2049         if (scrollViewParent)
2050             return scrollViewParent;
2051         
2052         // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
2053         if (m_object->isTreeItem()) {
2054             AccessibilityObject* parent = m_object->parentObjectUnignored();
2055             while (parent) {
2056                 if (parent->isTree())
2057                     return parent->wrapper();
2058                 parent = parent->parentObjectUnignored();
2059             }
2060         }
2061         
2062         AccessibilityObject* parent = m_object->parentObjectUnignored();
2063         if (!parent)
2064             return nil;
2065
2066         // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
2067         // should be reported directly as such.
2068         if (m_object->isWebArea() && parent->isAttachment())
2069             return [parent->wrapper() attachmentView];
2070         
2071         return parent->wrapper();
2072     }
2073
2074     if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute]) {
2075         if (m_object->children().isEmpty()) {
2076             NSArray* children = [self renderWidgetChildren];
2077             if (children != nil)
2078                 return children;
2079         }
2080
2081         // The tree's (AXOutline) children are supposed to be its rows and columns.
2082         // The ARIA spec doesn't have columns, so we just need rows.
2083         if (m_object->isTree())
2084             return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
2085
2086         // A tree item should only expose its content as its children (not its rows)
2087         if (m_object->isTreeItem()) {
2088             AccessibilityObject::AccessibilityChildrenVector contentCopy;
2089             m_object->ariaTreeItemContent(contentCopy);
2090             return convertToNSArray(contentCopy);
2091         }
2092         
2093         return convertToNSArray(m_object->children());
2094     }
2095     
2096     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2097         if (m_object->isListBox()) {
2098             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2099             m_object->selectedChildren(selectedChildrenCopy);
2100             return convertToNSArray(selectedChildrenCopy);
2101         }
2102         return nil;
2103     }
2104     
2105     if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
2106         if (m_object->isListBox()) {
2107             AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
2108             m_object->visibleChildren(visibleChildrenCopy);
2109             return convertToNSArray(visibleChildrenCopy);
2110         }
2111         else if (m_object->isList())
2112             return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
2113
2114         return nil;
2115     }
2116     
2117     
2118     if (m_object->isWebArea()) {
2119         if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
2120             AccessibilityObject::AccessibilityChildrenVector links;
2121             static_cast<AccessibilityRenderObject*>(m_object)->getDocumentLinks(links);
2122             return convertToNSArray(links);
2123         }
2124         if ([attributeName isEqualToString:@"AXLoaded"])
2125             return [NSNumber numberWithBool:m_object->isLoaded()];
2126         if ([attributeName isEqualToString:@"AXLayoutCount"])
2127             return [NSNumber numberWithInt:m_object->layoutCount()];
2128         if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
2129             return [NSNumber numberWithDouble:m_object->estimatedLoadingProgress()];
2130     }
2131     
2132     if (m_object->isTextControl()) {
2133         if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
2134             int length = m_object->textLength();
2135             if (length < 0)
2136                 return nil;
2137             return [NSNumber numberWithUnsignedInt:length];
2138         }
2139         if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2140             String selectedText = m_object->selectedText();
2141             if (selectedText.isNull())
2142                 return nil;
2143             return (NSString*)selectedText;
2144         }
2145         if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2146             PlainTextRange textRange = m_object->selectedTextRange();
2147             if (textRange.isNull())
2148                 return [NSValue valueWithRange:NSMakeRange(0, 0)];
2149             return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
2150         }
2151         // TODO: Get actual visible range. <rdar://problem/4712101>
2152         if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2153             return m_object->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, m_object->textLength())];
2154         if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
2155             // if selectionEnd > 0, then there is selected text and this question should not be answered
2156             if (m_object->isPasswordField() || m_object->selectionEnd() > 0)
2157                 return nil;
2158
2159             AccessibilityObject* focusedObject = m_object->focusedUIElement();
2160             if (focusedObject != m_object)
2161                 return nil;
2162
2163             VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
2164             int lineNumber = m_object->lineForPosition(focusedPosition);
2165             if (lineNumber < 0)
2166                 return nil;
2167
2168             return [NSNumber numberWithInt:lineNumber];
2169         }
2170     }
2171     
2172     if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
2173         KURL url = m_object->url();
2174         if (url.isNull())
2175             return nil;
2176         return (NSURL*)url;
2177     }
2178
2179     if (m_object->isSpinButton()) {
2180         if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute])
2181             return toAccessibilitySpinButton(m_object)->incrementButton()->wrapper();
2182         if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute])
2183             return toAccessibilitySpinButton(m_object)->decrementButton()->wrapper();
2184     }
2185     
2186     if ([attributeName isEqualToString: @"AXVisited"])
2187         return [NSNumber numberWithBool: m_object->isVisited()];
2188     
2189     if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
2190         if (m_object->isAttachment()) {
2191             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute]) 
2192                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
2193         }
2194         
2195         return [self accessibilityTitle];
2196     }
2197     
2198     if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
2199         if (m_object->isAttachment()) {
2200             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
2201                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
2202         }
2203         return [self accessibilityDescription];
2204     }
2205
2206     if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2207         if (m_object->isAttachment()) {
2208             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute]) 
2209                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
2210         }
2211         if (m_object->supportsRangeValue())
2212             return [NSNumber numberWithFloat:m_object->valueForRange()];
2213         if (m_object->roleValue() == SliderThumbRole)
2214             return [NSNumber numberWithFloat:m_object->parentObject()->valueForRange()];
2215         if (m_object->isHeading())
2216             return [NSNumber numberWithInt:m_object->headingLevel()];
2217         
2218         if (m_object->isCheckboxOrRadio()) {
2219             switch (m_object->checkboxOrRadioValue()) {
2220             case ButtonStateOff:
2221                 return [NSNumber numberWithInt:0];
2222             case ButtonStateOn:
2223                 return [NSNumber numberWithInt:1];
2224             case ButtonStateMixed:
2225                 return [NSNumber numberWithInt:2];
2226             }
2227         }
2228
2229         // radio groups return the selected radio button as the AXValue
2230         if (m_object->isRadioGroup()) {
2231             AccessibilityObject* radioButton = m_object->selectedRadioButton();
2232             if (!radioButton)
2233                 return nil;
2234             return radioButton->wrapper();
2235         }
2236         
2237         if (m_object->isTabList()) {
2238             AccessibilityObject* tabItem = m_object->selectedTabItem();
2239             if (!tabItem)
2240                 return nil;
2241             return tabItem->wrapper();
2242         }
2243         
2244         if (m_object->isTabItem())
2245             return [NSNumber numberWithInt:m_object->isSelected()];
2246         
2247         return m_object->stringValue();
2248     }
2249
2250     if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute])
2251         return [NSNumber numberWithFloat:m_object->minValueForRange()];
2252
2253     if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute])
2254         return [NSNumber numberWithFloat:m_object->maxValueForRange()];
2255
2256     if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2257         return [self accessibilityHelpText];
2258
2259     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2260         return [NSNumber numberWithBool: m_object->isFocused()];
2261
2262     if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2263         return [NSNumber numberWithBool: m_object->isEnabled()];
2264
2265     if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2266         IntSize s = m_object->pixelSnappedSize();
2267         return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2268     }
2269
2270     if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2271         return [self position];
2272
2273     if ([attributeName isEqualToString: NSAccessibilityWindowAttribute] ||
2274         [attributeName isEqualToString: NSAccessibilityTopLevelUIElementAttribute]) {
2275         
2276         id remoteParent = [self remoteAccessibilityParentObject];
2277         if (remoteParent)
2278             return [remoteParent accessibilityAttributeValue:attributeName];
2279         
2280         FrameView* fv = m_object->documentFrameView();
2281         if (fv)
2282             return [fv->platformWidget() window];
2283         return nil;
2284     }
2285     
2286     if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2287         AtomicString accessKey = m_object->accessKey();
2288         if (accessKey.isNull())
2289             return nil;
2290         return accessKey;
2291     }
2292     
2293     if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2294         if (m_object->isTabList()) {
2295             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2296             m_object->tabChildren(tabsChildren);
2297             return convertToNSArray(tabsChildren);
2298         }
2299     }
2300     
2301     if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2302         // The contents of a tab list are all the children except the tabs.
2303         if (m_object->isTabList()) {
2304             AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2305             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2306             m_object->tabChildren(tabsChildren);
2307
2308             AccessibilityObject::AccessibilityChildrenVector contents;
2309             unsigned childrenSize = children.size();
2310             for (unsigned k = 0; k < childrenSize; ++k) {
2311                 if (tabsChildren.find(children[k]) == WTF::notFound)
2312                     contents.append(children[k]);
2313             }
2314             return convertToNSArray(contents);
2315         } else if (m_object->isScrollView()) {
2316             AccessibilityObject::AccessibilityChildrenVector children = m_object->children();
2317             
2318             // A scrollView's contents are everything except the scroll bars.
2319             AccessibilityObject::AccessibilityChildrenVector contents;
2320             unsigned childrenSize = children.size();
2321             for (unsigned k = 0; k < childrenSize; ++k) {
2322                 if (!children[k]->isScrollbar())
2323                     contents.append(children[k]);
2324             }
2325             return convertToNSArray(contents);            
2326         }
2327     }    
2328     
2329     if (m_object->isAccessibilityTable()) {
2330         // TODO: distinguish between visible and non-visible rows
2331         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || 
2332             [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2333             return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->rows());
2334         }
2335         // TODO: distinguish between visible and non-visible columns
2336         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute] || 
2337             [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute]) {
2338             return convertToNSArray(static_cast<AccessibilityTable*>(m_object)->columns());
2339         }
2340         
2341         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2342             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2343             m_object->selectedChildren(selectedChildrenCopy);
2344             return convertToNSArray(selectedChildrenCopy);
2345         }
2346         
2347         // HTML tables don't support these
2348         if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute] || 
2349             [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2350             return nil;
2351         
2352         if ([attributeName isEqualToString:(NSString *)kAXColumnHeaderUIElementsAttribute]) {
2353             AccessibilityObject::AccessibilityChildrenVector columnHeaders;
2354             static_cast<AccessibilityTable*>(m_object)->columnHeaders(columnHeaders);
2355             return convertToNSArray(columnHeaders);            
2356         }
2357         
2358         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2359             AccessibilityObject* headerContainer = static_cast<AccessibilityTable*>(m_object)->headerContainer();
2360             if (headerContainer)
2361                 return headerContainer->wrapper();
2362             return nil;
2363         }
2364
2365         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute]) {
2366             AccessibilityObject::AccessibilityChildrenVector rowHeaders;
2367             static_cast<AccessibilityTable*>(m_object)->rowHeaders(rowHeaders);
2368             return convertToNSArray(rowHeaders);                        
2369         }
2370         
2371         if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute]) {
2372             AccessibilityObject::AccessibilityChildrenVector cells;
2373             static_cast<AccessibilityTable*>(m_object)->cells(cells);
2374             return convertToNSArray(cells);
2375         }        
2376     }
2377     
2378     if (m_object->isTableColumn()) {
2379         if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2380             return [NSNumber numberWithInt:static_cast<AccessibilityTableColumn*>(m_object)->columnIndex()];
2381         
2382         // rows attribute for a column is the list of all the elements in that column at each row
2383         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute] || 
2384             [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute]) {
2385             return convertToNSArray(static_cast<AccessibilityTableColumn*>(m_object)->children());
2386         }
2387         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2388             AccessibilityObject* header = static_cast<AccessibilityTableColumn*>(m_object)->headerObject();
2389             if (!header)
2390                 return nil;
2391             return header->wrapper();
2392         }
2393     }
2394     
2395     if (m_object->isTableCell()) {
2396         if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2397             pair<int, int> rowRange;
2398             static_cast<AccessibilityTableCell*>(m_object)->rowIndexRange(rowRange);
2399             return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2400         }  
2401         if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2402             pair<int, int> columnRange;
2403             static_cast<AccessibilityTableCell*>(m_object)->columnIndexRange(columnRange);
2404             return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2405         }  
2406     }
2407     
2408     if (m_object->isTree()) {
2409         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2410             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2411             m_object->selectedChildren(selectedChildrenCopy);
2412             return convertToNSArray(selectedChildrenCopy);
2413         }
2414         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2415             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2416             m_object->ariaTreeRows(rowsCopy);
2417             return convertToNSArray(rowsCopy);            
2418         }
2419         
2420         // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2421         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2422             return [NSArray array];
2423     }
2424
2425     if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2426         if (m_object->isTreeItem()) {
2427             AccessibilityObject* parent = m_object->parentObject();
2428             for (; parent && !parent->isTree(); parent = parent->parentObject())
2429             { }
2430             
2431             if (!parent)
2432                 return nil;
2433             
2434             // Find the index of this item by iterating the parents.
2435             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2436             parent->ariaTreeRows(rowsCopy);
2437             size_t count = rowsCopy.size();
2438             for (size_t k = 0; k < count; ++k)
2439                 if (rowsCopy[k]->wrapper() == self)
2440                     return [NSNumber numberWithUnsignedInt:k];
2441             
2442             return nil;
2443         }
2444         if (m_object->isTableRow()) {
2445             if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2446                 return [NSNumber numberWithInt:static_cast<AccessibilityTableRow*>(m_object)->rowIndex()];
2447         }
2448     }    
2449     
2450     // The rows that are considered inside this row. 
2451     if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2452         if (m_object->isTreeItem()) {
2453             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2454             m_object->ariaTreeItemDisclosedRows(rowsCopy);
2455             return convertToNSArray(rowsCopy);    
2456         } else if (m_object->isARIATreeGridRow()) {
2457             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2458             static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedRows(rowsCopy);
2459             return convertToNSArray(rowsCopy);    
2460         }
2461     }
2462     
2463     // The row that contains this row. It should be the same as the first parent that is a treeitem.
2464     if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2465         if (m_object->isTreeItem()) {
2466             AccessibilityObject* parent = m_object->parentObject();
2467             while (parent) {
2468                 if (parent->isTreeItem())
2469                     return parent->wrapper();
2470                 // If the parent is the tree itself, then this value == nil.
2471                 if (parent->isTree())
2472                     return nil;
2473                 parent = parent->parentObject();
2474             }
2475             return nil;
2476         } else if (m_object->isARIATreeGridRow()) {
2477             AccessibilityObject* row = static_cast<AccessibilityARIAGridRow*>(m_object)->disclosedByRow();
2478             if (!row)
2479                 return nil;
2480             return row->wrapper();
2481         }
2482     }
2483
2484     if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {
2485         // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)
2486         int level = m_object->hierarchicalLevel();
2487         if (level > 0)
2488             level -= 1;
2489         return [NSNumber numberWithInt:level];
2490     }
2491     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2492         return [NSNumber numberWithBool:m_object->isExpanded()];
2493     
2494     if ((m_object->isListBox() || m_object->isList()) && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2495         return NSAccessibilityVerticalOrientationValue;
2496
2497     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2498         return [self textMarkerRangeForSelection];
2499     
2500     if (m_object->renderer()) {
2501         if ([attributeName isEqualToString: @"AXStartTextMarker"])
2502             return [self textMarkerForVisiblePosition:startOfDocument(m_object->renderer()->document())];
2503         if ([attributeName isEqualToString: @"AXEndTextMarker"])
2504             return [self textMarkerForVisiblePosition:endOfDocument(m_object->renderer()->document())];
2505     }
2506     
2507     if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2508         return [NSNumber numberWithInt:m_object->blockquoteLevel()];
2509     if ([attributeName isEqualToString:@"AXTableLevel"])
2510         return [NSNumber numberWithInt:m_object->tableLevel()];
2511     
2512     if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2513         AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2514         m_object->linkedUIElements(linkedUIElements);
2515         if (linkedUIElements.size() == 0)
2516             return nil;
2517         return convertToNSArray(linkedUIElements);
2518     }
2519
2520     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2521         return [NSNumber numberWithBool:m_object->isSelected()];
2522
2523     if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && m_object->isMenuButton()) {
2524         AccessibilityObject* uiElement = static_cast<AccessibilityRenderObject*>(m_object)->menuForMenuButton();
2525         if (uiElement)
2526             return [NSArray arrayWithObject:uiElement->wrapper()];
2527     }
2528
2529     if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2530         if (!m_object->exposesTitleUIElement())
2531             return nil;
2532         
2533         AccessibilityObject* obj = m_object->titleUIElement();
2534         if (obj)
2535             return obj->wrapper();
2536         return nil;
2537     }
2538     
2539     if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute])
2540         return m_object->valueDescription();
2541     
2542     if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2543         AccessibilityOrientation elementOrientation = m_object->orientation();
2544         if (elementOrientation == AccessibilityOrientationVertical)
2545             return NSAccessibilityVerticalOrientationValue;
2546         if (elementOrientation == AccessibilityOrientationHorizontal)
2547             return NSAccessibilityHorizontalOrientationValue;
2548         return nil;
2549     }
2550     
2551     if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2552         AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationHorizontal);
2553         if (scrollBar)
2554             return scrollBar->wrapper();
2555         return nil;
2556     }
2557     if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2558         AccessibilityObject* scrollBar = m_object->scrollBar(AccessibilityOrientationVertical);
2559         if (scrollBar)
2560             return scrollBar->wrapper();
2561         return nil;
2562     }
2563     
2564     if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2565         switch (m_object->sortDirection()) {
2566         case SortDirectionAscending:
2567             return NSAccessibilityAscendingSortDirectionValue;
2568         case SortDirectionDescending:
2569             return NSAccessibilityDescendingSortDirectionValue;
2570         default:
2571             return NSAccessibilityUnknownSortDirectionValue;
2572         }
2573     }
2574     
2575     if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute]) 
2576         return m_object->language();
2577     
2578     if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2579         return [NSNumber numberWithBool:m_object->isExpanded()];
2580     
2581     if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2582         return [NSNumber numberWithBool:m_object->isRequired()];
2583
2584     if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2585         return m_object->invalidStatus();
2586     
2587     if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2588         AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2589         m_object->ariaOwnsElements(ariaOwns);
2590         return convertToNSArray(ariaOwns);
2591     }
2592     
2593     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2594         return [NSNumber numberWithBool:m_object->isARIAGrabbed()];
2595     
2596     if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2597         Vector<String> dropEffects;
2598         m_object->determineARIADropEffects(dropEffects);
2599         size_t length = dropEffects.size();
2600
2601         NSMutableArray* dropEffectsArray = [NSMutableArray arrayWithCapacity:length];
2602         for (size_t i = 0; i < length; ++i)
2603             [dropEffectsArray addObject:dropEffects[i]];
2604         return dropEffectsArray;
2605     }
2606     
2607     if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2608         return m_object->placeholderValue();
2609     
2610     if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
2611         return [NSNumber numberWithBool:m_object->ariaHasPopup()];
2612     
2613     // ARIA Live region attributes.
2614     if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
2615         return m_object->ariaLiveRegionStatus();
2616     if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
2617          return m_object->ariaLiveRegionRelevant();
2618     if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
2619         return [NSNumber numberWithBool:m_object->ariaLiveRegionAtomic()];
2620     if ([attributeName isEqualToString:NSAccessibilityARIABusyAttribute])
2621         return [NSNumber numberWithBool:m_object->ariaLiveRegionBusy()];
2622
2623     // MathML Attributes.
2624     if (m_object->isMathElement()) {
2625         if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])
2626             return (m_object->mathRootIndexObject()) ? m_object->mathRootIndexObject()->wrapper() : 0;
2627         if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])
2628             return (m_object->mathRadicandObject()) ? m_object->mathRadicandObject()->wrapper() : 0;
2629         if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
2630             return (m_object->mathNumeratorObject()) ? m_object->mathNumeratorObject()->wrapper() : 0;
2631         if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
2632             return (m_object->mathDenominatorObject()) ? m_object->mathDenominatorObject()->wrapper() : 0;
2633         if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])
2634             return (m_object->mathBaseObject()) ? m_object->mathBaseObject()->wrapper() : 0;
2635         if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])
2636             return (m_object->mathSubscriptObject()) ? m_object->mathSubscriptObject()->wrapper() : 0;
2637         if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])
2638             return (m_object->mathSuperscriptObject()) ? m_object->mathSuperscriptObject()->wrapper() : 0;
2639         if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])
2640             return (m_object->mathUnderObject()) ? m_object->mathUnderObject()->wrapper() : 0;
2641         if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])
2642             return (m_object->mathOverObject()) ? m_object->mathOverObject()->wrapper() : 0;
2643         if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])
2644             return m_object->mathFencedOpenString();
2645         if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])
2646             return m_object->mathFencedCloseString();
2647     }
2648     
2649     // this is used only by DumpRenderTree for testing
2650     if ([attributeName isEqualToString:@"AXClickPoint"])
2651         return [NSValue valueWithPoint:m_object->clickPoint()];
2652     
2653     // This is used by DRT to verify CSS3 speech works.
2654     if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"]) {
2655         ESpeak speakProperty = m_object->speakProperty();
2656         switch (speakProperty) {
2657         case SpeakNone:
2658             return @"none";
2659         case SpeakSpellOut:
2660             return @"spell-out";
2661         case SpeakDigits:
2662             return @"digits";
2663         case SpeakLiteralPunctuation:
2664             return @"literal-punctuation";
2665         case SpeakNoPunctuation:
2666             return @"no-punctuation";
2667         default:
2668         case SpeakNormal:
2669             return @"normal";
2670         }
2671     }
2672
2673     // Used by DRT to find an accessible node by its element id.
2674     if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])
2675         return m_object->getAttribute(idAttr);
2676     
2677     return nil;
2678 }
2679
2680 - (id)accessibilityFocusedUIElement
2681 {
2682     if (![self updateObjectBackingStore])
2683         return nil;
2684
2685     RefPtr<AccessibilityObject> focusedObj = m_object->focusedUIElement();
2686
2687     if (!focusedObj)
2688         return nil;
2689     
2690     return focusedObj->wrapper();
2691 }
2692
2693 - (id)accessibilityHitTest:(NSPoint)point
2694 {
2695     if (![self updateObjectBackingStore])
2696         return nil;
2697
2698     m_object->updateChildrenIfNecessary();
2699     RefPtr<AccessibilityObject> axObject = m_object->accessibilityHitTest(IntPoint(point));
2700     if (axObject)
2701         return NSAccessibilityUnignoredAncestor(axObject->wrapper());
2702     return NSAccessibilityUnignoredAncestor(self);
2703 }
2704
2705 - (BOOL)accessibilityIsAttributeSettable:(NSString*)attributeName
2706 {
2707     if (![self updateObjectBackingStore])
2708         return nil;
2709
2710     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2711         return YES;
2712
2713     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2714         return m_object->canSetFocusAttribute();
2715
2716     if ([attributeName isEqualToString: NSAccessibilityValueAttribute])
2717         return m_object->canSetValueAttribute();
2718
2719     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2720         return m_object->canSetSelectedAttribute();
2721     
2722     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute])
2723         return m_object->canSetSelectedChildrenAttribute();
2724
2725     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2726         return m_object->canSetExpandedAttribute();
2727
2728     if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute])
2729         return YES;
2730
2731     if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute] ||
2732         [attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute] ||
2733         [attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2734         return m_object->canSetTextRangeAttributes();
2735     
2736     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2737         return YES;
2738     
2739     return NO;
2740 }
2741
2742 // accessibilityShouldUseUniqueId is an AppKit method we override so that
2743 // objects will be given a unique ID, and therefore allow AppKit to know when they
2744 // become obsolete (e.g. when the user navigates to a new web page, making this one
2745 // unrendered but not deallocated because it is in the back/forward cache).
2746 // It is important to call NSAccessibilityUnregisterUniqueIdForUIElement in the
2747 // appropriate place (e.g. dealloc) to remove these non-retained references from
2748 // AppKit's id mapping tables. We do this in detach by calling unregisterUniqueIdForUIElement.
2749 //
2750 // Registering an object is also required for observing notifications. Only registered objects can be observed.
2751 - (BOOL)accessibilityIsIgnored
2752 {
2753     if (![self updateObjectBackingStore])
2754         return YES;
2755
2756     if (m_object->isAttachment())
2757         return [[self attachmentView] accessibilityIsIgnored];
2758     return m_object->accessibilityIsIgnored();
2759 }
2760
2761 - (NSArray* )accessibilityParameterizedAttributeNames
2762 {
2763     if (![self updateObjectBackingStore])
2764         return nil;
2765
2766     if (m_object->isAttachment()) 
2767         return nil;
2768
2769     static NSArray* paramAttrs = nil;
2770     static NSArray* textParamAttrs = nil;
2771     static NSArray* tableParamAttrs = nil;
2772     static NSArray* webAreaParamAttrs = nil;
2773     if (paramAttrs == nil) {
2774         paramAttrs = [[NSArray alloc] initWithObjects:
2775                       @"AXUIElementForTextMarker",
2776                       @"AXTextMarkerRangeForUIElement",
2777                       @"AXLineForTextMarker",
2778                       @"AXTextMarkerRangeForLine",
2779                       @"AXStringForTextMarkerRange",
2780                       @"AXTextMarkerForPosition",
2781                       @"AXBoundsForTextMarkerRange",
2782                       @"AXAttributedStringForTextMarkerRange",
2783                       @"AXTextMarkerRangeForUnorderedTextMarkers",
2784                       @"AXNextTextMarkerForTextMarker",
2785                       @"AXPreviousTextMarkerForTextMarker",
2786                       @"AXLeftWordTextMarkerRangeForTextMarker",
2787                       @"AXRightWordTextMarkerRangeForTextMarker",
2788                       @"AXLeftLineTextMarkerRangeForTextMarker",
2789                       @"AXRightLineTextMarkerRangeForTextMarker",
2790                       @"AXSentenceTextMarkerRangeForTextMarker",
2791                       @"AXParagraphTextMarkerRangeForTextMarker",
2792                       @"AXNextWordEndTextMarkerForTextMarker",
2793                       @"AXPreviousWordStartTextMarkerForTextMarker",
2794                       @"AXNextLineEndTextMarkerForTextMarker",
2795                       @"AXPreviousLineStartTextMarkerForTextMarker",
2796                       @"AXNextSentenceEndTextMarkerForTextMarker",
2797                       @"AXPreviousSentenceStartTextMarkerForTextMarker",
2798                       @"AXNextParagraphEndTextMarkerForTextMarker",
2799                       @"AXPreviousParagraphStartTextMarkerForTextMarker",
2800                       @"AXStyleTextMarkerRangeForTextMarker",
2801                       @"AXLengthForTextMarkerRange",
2802                       NSAccessibilityBoundsForRangeParameterizedAttribute,
2803                       NSAccessibilityStringForRangeParameterizedAttribute,
2804                       NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
2805                       nil];
2806     }
2807
2808     if (textParamAttrs == nil) {
2809         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2810         [tempArray addObject:(NSString*)kAXLineForIndexParameterizedAttribute];
2811         [tempArray addObject:(NSString*)kAXRangeForLineParameterizedAttribute];
2812         [tempArray addObject:(NSString*)kAXStringForRangeParameterizedAttribute];
2813         [tempArray addObject:(NSString*)kAXRangeForPositionParameterizedAttribute];
2814         [tempArray addObject:(NSString*)kAXRangeForIndexParameterizedAttribute];
2815         [tempArray addObject:(NSString*)kAXBoundsForRangeParameterizedAttribute];
2816         [tempArray addObject:(NSString*)kAXRTFForRangeParameterizedAttribute];
2817         [tempArray addObject:(NSString*)kAXAttributedStringForRangeParameterizedAttribute];
2818         [tempArray addObject:(NSString*)kAXStyleRangeForIndexParameterizedAttribute];
2819         textParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2820         [tempArray release];
2821     }
2822     if (tableParamAttrs == nil) {
2823         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2824         [tempArray addObject:NSAccessibilityCellForColumnAndRowParameterizedAttribute];
2825         tableParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2826         [tempArray release];
2827     }
2828     if (!webAreaParamAttrs) {
2829         NSMutableArray* tempArray = [[NSMutableArray alloc] initWithArray:paramAttrs];
2830         [tempArray addObject:NSAccessibilityTextMarkerForIndexParameterizedAttribute];
2831         [tempArray addObject:NSAccessibilityTextMarkerIsValidParameterizedAttribute];
2832         [tempArray addObject:NSAccessibilityIndexForTextMarkerParameterizedAttribute];
2833         webAreaParamAttrs = [[NSArray alloc] initWithArray:tempArray];
2834         [tempArray release];
2835     }
2836     
2837     if (m_object->isPasswordField())
2838         return [NSArray array];
2839     
2840     if (!m_object->isAccessibilityRenderObject())
2841         return paramAttrs;
2842
2843     if (m_object->isTextControl())
2844         return textParamAttrs;
2845     
2846     if (m_object->isAccessibilityTable())
2847         return tableParamAttrs;
2848     
2849     if (m_object->isMenuRelated())
2850         return nil;
2851
2852     if (m_object->isWebArea())
2853         return webAreaParamAttrs;
2854     
2855     return paramAttrs;
2856 }
2857
2858 - (void)accessibilityPerformPressAction
2859 {
2860     if (![self updateObjectBackingStore])
2861         return;
2862
2863     if (m_object->isAttachment())
2864         [[self attachmentView] accessibilityPerformAction:NSAccessibilityPressAction];
2865     else
2866         m_object->press();    
2867 }
2868
2869 - (void)accessibilityPerformIncrementAction
2870 {
2871     if (![self updateObjectBackingStore])
2872         return;
2873
2874     if (m_object->isAttachment())
2875         [[self attachmentView] accessibilityPerformAction:NSAccessibilityIncrementAction];
2876     else
2877         m_object->increment();    
2878 }
2879
2880 - (void)accessibilityPerformDecrementAction
2881 {
2882     if (![self updateObjectBackingStore])
2883         return;
2884
2885     if (m_object->isAttachment())
2886         [[self attachmentView] accessibilityPerformAction:NSAccessibilityDecrementAction];
2887     else
2888         m_object->decrement();    
2889 }
2890
2891 - (void)accessibilityPerformShowMenuAction
2892 {
2893     if (m_object->roleValue() == ComboBoxRole)
2894         m_object->setIsExpanded(true);
2895     else {
2896         // This needs to be performed in an iteration of the run loop that did not start from an AX call. 
2897         // If it's the same run loop iteration, the menu open notification won't be sent
2898         [self performSelector:@selector(accessibilityShowContextMenu) withObject:nil afterDelay:0.0];
2899     }
2900 }
2901
2902 - (void)accessibilityShowContextMenu
2903 {    
2904     Page* page = m_object->page();
2905     if (!page)
2906         return;
2907     
2908     IntRect rect = pixelSnappedIntRect(m_object->elementRect());
2909     FrameView* frameView = m_object->documentFrameView();
2910
2911     // On WK2, we need to account for the scroll position.
2912     // On WK1, this isn't necessary, it's taken care of by the attachment views.
2913     if (frameView && !frameView->platformWidget()) {
2914         // Find the appropriate scroll view to use to convert the contents to the window.
2915         for (AccessibilityObject* parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
2916             if (parent->isAccessibilityScrollView()) {
2917                 ScrollView* scrollView = toAccessibilityScrollView(parent)->scrollView();
2918                 rect = scrollView->contentsToRootView(rect);
2919                 break;
2920             }
2921         }
2922     }
2923     
2924     page->contextMenuController()->showContextMenuAt(page->mainFrame(), rect.center());
2925 }
2926
2927 - (void)accessibilityPerformAction:(NSString*)action
2928 {
2929     if (![self updateObjectBackingStore])
2930         return;
2931
2932     if ([action isEqualToString:NSAccessibilityPressAction])
2933         [self accessibilityPerformPressAction];
2934     
2935     else if ([action isEqualToString:NSAccessibilityShowMenuAction])
2936         [self accessibilityPerformShowMenuAction];
2937
2938     else if ([action isEqualToString:NSAccessibilityIncrementAction])
2939         [self accessibilityPerformIncrementAction];
2940
2941     else if ([action isEqualToString:NSAccessibilityDecrementAction])
2942         [self accessibilityPerformDecrementAction];
2943 }
2944
2945 - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attributeName
2946 {
2947     if (![self updateObjectBackingStore])
2948         return;
2949
2950     id textMarkerRange = nil;
2951     NSNumber*               number = nil;
2952     NSString*               string = nil;
2953     NSRange                 range = {0, 0};
2954     NSArray*                array = nil;
2955     
2956     // decode the parameter
2957     if (AXObjectIsTextMarkerRange(value))
2958         textMarkerRange = value;
2959
2960     else if ([value isKindOfClass:[NSNumber self]])
2961         number = value;
2962
2963     else if ([value isKindOfClass:[NSString self]])
2964         string = value;
2965     
2966     else if ([value isKindOfClass:[NSValue self]])
2967         range = [value rangeValue];
2968     
2969     else if ([value isKindOfClass:[NSArray self]])
2970         array = value;
2971     
2972     // handle the command
2973     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"]) {
2974         ASSERT(textMarkerRange);
2975         m_object->setSelectedVisiblePositionRange([self visiblePositionRangeForTextMarkerRange:textMarkerRange]);        
2976     } else if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute]) {
2977         ASSERT(number);
2978         m_object->setFocused([number intValue] != 0);
2979     } else if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2980         if (number && m_object->canSetNumericValue())
2981             m_object->setValue([number floatValue]);
2982         else if (string)
2983             m_object->setValue(string);
2984     } else if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute]) {
2985         if (!number)
2986             return;
2987         m_object->setSelected([number boolValue]);
2988     } else if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2989         if (!array || m_object->roleValue() != ListBoxRole)
2990             return;
2991         AccessibilityObject::AccessibilityChildrenVector selectedChildren;
2992         convertToVector(array, selectedChildren);
2993         static_cast<AccessibilityListBox*>(m_object)->setSelectedChildren(selectedChildren);
2994     } else if (m_object->isTextControl()) {
2995         if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2996             m_object->setSelectedText(string);
2997         } else if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2998             m_object->setSelectedTextRange(PlainTextRange(range.location, range.length));
2999         } else if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute]) {
3000             m_object->makeRangeVisible(PlainTextRange(range.location, range.length));
3001         }
3002     } else if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
3003         m_object->setIsExpanded([number boolValue]);
3004     else if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
3005         AccessibilityObject::AccessibilityChildrenVector selectedRows;
3006         convertToVector(array, selectedRows);
3007         if (m_object->isTree() || m_object->isAccessibilityTable())
3008             m_object->setSelectedRows(selectedRows);
3009     } else if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
3010         m_object->setARIAGrabbed([number boolValue]);
3011 }
3012
3013 static RenderObject* rendererForView(NSView* view)
3014 {
3015     if (![view conformsToProtocol:@protocol(WebCoreFrameView)])
3016         return 0;
3017
3018     NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view;
3019     Frame* frame = [frameView _web_frame];
3020     if (!frame)
3021         return 0;
3022
3023     Node* node = frame->document()->ownerElement();
3024     if (!node)
3025         return 0;
3026
3027     return node->renderer();
3028 }
3029
3030 - (id)_accessibilityParentForSubview:(NSView*)subview
3031 {   
3032     RenderObject* renderer = rendererForView(subview);
3033     if (!renderer)
3034         return nil;
3035
3036     AccessibilityObject* obj = renderer->document()->axObjectCache()->getOrCreate(renderer);
3037     if (obj)
3038         return obj->parentObjectUnignored()->wrapper();
3039     return nil;
3040 }
3041
3042 - (NSString*)accessibilityActionDescription:(NSString*)action
3043 {
3044     // we have no custom actions
3045     return NSAccessibilityActionDescription(action);
3046 }
3047
3048 // The CFAttributedStringType representation of the text associated with this accessibility
3049 // object that is specified by the given range.
3050 - (NSAttributedString*)doAXAttributedStringForRange:(NSRange)range
3051 {
3052     PlainTextRange textRange = PlainTextRange(range.location, range.length);
3053     VisiblePositionRange visiblePosRange = m_object->visiblePositionRangeForRange(textRange);
3054     return [self doAXAttributedStringForTextMarkerRange:[self textMarkerRangeFromVisiblePositions:visiblePosRange.start endPosition:visiblePosRange.end]];
3055 }
3056
3057 - (NSRange)_convertToNSRange:(Range*)range
3058 {
3059     NSRange result = NSMakeRange(NSNotFound, 0);
3060     if (!range || !range->startContainer())
3061         return result;
3062
3063     Document* document = m_object->document();
3064     if (!document)
3065         return result;
3066
3067     size_t location;
3068     size_t length;
3069     TextIterator::getLocationAndLengthFromRange(document->documentElement(), range, location, length);
3070     result.location = location;
3071     result.length = length;
3072
3073     return result;
3074 }
3075
3076 - (NSInteger)_indexForTextMarker:(id)marker
3077 {
3078     if (!marker)
3079         return NSNotFound;
3080     
3081     VisibleSelection selection([self visiblePositionForTextMarker:marker]);    
3082     return [self _convertToNSRange:selection.toNormalizedRange().get()].location;
3083 }
3084
3085 - (id)_textMarkerForIndex:(NSInteger)textIndex
3086 {
3087     Document* document = m_object->document();
3088     if (!document)
3089         return nil;
3090     
3091     PassRefPtr<Range> textRange = TextIterator::rangeFromLocationAndLength(document->documentElement(), textIndex, 0);
3092     if (!textRange || !textRange->boundaryPointsValid())
3093         return nil;
3094
3095     VisiblePosition position(textRange->startPosition());
3096     return [self textMarkerForVisiblePosition:position];
3097 }
3098
3099 // The RTF representation of the text associated with this accessibility object that is
3100 // specified by the given range.
3101 - (NSData*)doAXRTFForRange:(NSRange)range
3102 {
3103     NSAttributedString* attrString = [self doAXAttributedStringForRange:range];
3104     return [attrString RTFFromRange: NSMakeRange(0, [attrString length]) documentAttributes: nil];
3105 }
3106
3107 - (id)accessibilityAttributeValue:(NSString*)attribute forParameter:(id)parameter
3108 {
3109     id textMarker = nil;
3110     id textMarkerRange = nil;
3111     NSNumber* number = nil;
3112     NSArray* array = nil;
3113     NSDictionary* dictionary = nil;
3114     RefPtr<AccessibilityObject> uiElement = 0;
3115     NSPoint point = NSZeroPoint;
3116     bool pointSet = false;
3117     NSRange range = {0, 0};
3118     bool rangeSet = false;
3119     
3120     // basic parameter validation
3121     if (!m_object || !attribute || !parameter)
3122         return nil;
3123
3124     if (![self updateObjectBackingStore])
3125         return nil;
3126     
3127     // common parameter type check/casting.  Nil checks in handlers catch wrong type case.
3128     // NOTE: This assumes nil is not a valid parameter, because it is indistinguishable from
3129     // a parameter of the wrong type.
3130     if (AXObjectIsTextMarker(parameter))
3131         textMarker = parameter;
3132
3133     else if (AXObjectIsTextMarkerRange(parameter))
3134         textMarkerRange = parameter;
3135
3136     else if ([parameter isKindOfClass:[WebAccessibilityObjectWrapper self]])
3137         uiElement = [(WebAccessibilityObjectWrapper*)parameter accessibilityObject];
3138
3139     else if ([parameter isKindOfClass:[NSNumber self]])
3140         number = parameter;
3141
3142     else if ([parameter isKindOfClass:[NSArray self]])
3143         array = parameter;
3144
3145     else if ([parameter isKindOfClass:[NSDictionary self]])
3146         dictionary = parameter;
3147
3148     else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSPoint)) == 0) {
3149         pointSet = true;
3150         point = [(NSValue*)parameter pointValue];
3151
3152     } else if ([parameter isKindOfClass:[NSValue self]] && strcmp([(NSValue*)parameter objCType], @encode(NSRange)) == 0) {
3153         rangeSet = true;
3154         range = [(NSValue*)parameter rangeValue];
3155     } else {
3156         // Attribute type is not supported. Allow super to handle.
3157         return [super accessibilityAttributeValue:attribute forParameter:parameter];
3158     }
3159     
3160     // dispatch
3161     if ([attribute isEqualToString:NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute]) {
3162         AccessibilityObject* startObject = 0;
3163         if ([[dictionary objectForKey:@"AXStartElement"] isKindOfClass:[WebAccessibilityObjectWrapper self]])
3164             startObject = [(WebAccessibilityObjectWrapper*)[dictionary objectForKey:@"AXStartElement"] accessibilityObject];
3165         
3166         AccessibilitySearchDirection searchDirection = SearchDirectionNext;
3167         if ([[dictionary objectForKey:@"AXDirection"] isKindOfClass:[NSString self]])
3168             searchDirection = ([(NSString*)[dictionary objectForKey:@"AXDirection"] isEqualToString:@"AXDirectionNext"]) ? SearchDirectionNext : SearchDirectionPrevious;
3169         
3170         AccessibilitySearchKey searchKey = AnyTypeSearchKey;
3171         if ([[dictionary objectForKey:@"AXSearchKey"] isKindOfClass:[NSString self]])
3172             searchKey = accessibilitySearchKeyForString((CFStringRef)[dictionary objectForKey:@"AXSearchKey"]);
3173         
3174         String searchText;
3175         if ([[dictionary objectForKey:@"AXSearchText"] isKindOfClass:[NSString self]])
3176             searchText = (CFStringRef)[dictionary objectForKey:@"AXSearchText"];
3177         
3178         unsigned resultsLimit = 0;
3179         if ([[dictionary objectForKey:@"AXResultsLimit"] isKindOfClass:[NSNumber self]])
3180             resultsLimit = [(NSNumber*)[dictionary objectForKey:@"AXResultsLimit"] unsignedIntValue];
3181         
3182         AccessibilitySearchCriteria criteria = {startObject, searchDirection, searchKey, &searchText, resultsLimit};
3183
3184         AccessibilityObject::AccessibilityChildrenVector results;
3185         m_object->findMatchingObjects(&criteria, results);
3186         
3187         return convertToNSArray(results);
3188     }
3189
3190     if ([attribute isEqualToString:NSAccessibilityTextMarkerIsValidParameterizedAttribute]) {
3191         VisiblePosition pos = [self visiblePositionForTextMarker:textMarker];
3192         return [NSNumber numberWithBool:!pos.isNull()];
3193     }
3194     if ([attribute isEqualToString:NSAccessibilityIndexForTextMarkerParameterizedAttribute]) {
3195         return [NSNumber numberWithInteger:[self _indexForTextMarker:textMarker]];
3196     }
3197     if ([attribute isEqualToString:NSAccessibilityTextMarkerForIndexParameterizedAttribute]) {
3198         return [self _textMarkerForIndex:[number integerValue]];
3199     }
3200     
3201     if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
3202         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3203         AccessibilityObject* axObject = m_object->accessibilityObjectForPosition(visiblePos);
3204         if (!axObject)
3205             return nil;
3206         return axObject->wrapper();
3207     }
3208
3209     if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {
3210         VisiblePositionRange vpRange = uiElement.get()->visiblePositionRange();
3211         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3212     }
3213
3214     if ([attribute isEqualToString:@"AXLineForTextMarker"]) {
3215         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3216         return [NSNumber numberWithUnsignedInt:m_object->lineForPosition(visiblePos)];
3217     }
3218
3219     if ([attribute isEqualToString:@"AXTextMarkerRangeForLine"]) {
3220         VisiblePositionRange vpRange = m_object->visiblePositionRangeForLine([number intValue]);
3221         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3222     }
3223
3224     if ([attribute isEqualToString:@"AXStringForTextMarkerRange"]) {
3225         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3226         return m_object->stringForVisiblePositionRange(visiblePosRange);
3227     }
3228
3229     if ([attribute isEqualToString:@"AXTextMarkerForPosition"]) {
3230         IntPoint webCorePoint = IntPoint(point);
3231         return pointSet ? [self textMarkerForVisiblePosition:m_object->visiblePositionForPoint(webCorePoint)] : nil;
3232     }
3233
3234     if ([attribute isEqualToString:@"AXBoundsForTextMarkerRange"]) {
3235         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3236         NSRect rect = m_object->boundsForVisiblePositionRange(visiblePosRange);
3237         return [NSValue valueWithRect:rect];
3238     }
3239     
3240     if ([attribute isEqualToString:NSAccessibilityBoundsForRangeParameterizedAttribute]) {
3241         VisiblePosition start = m_object->visiblePositionForIndex(range.location);
3242         VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
3243         if (start.isNull() || end.isNull())
3244             return nil;
3245         NSRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange(start, end));
3246         return [NSValue valueWithRect:rect];
3247     }
3248     
3249     if ([attribute isEqualToString:NSAccessibilityStringForRangeParameterizedAttribute]) {
3250         VisiblePosition start = m_object->visiblePositionForIndex(range.location);
3251         VisiblePosition end = m_object->visiblePositionForIndex(range.location+range.length);
3252         if (start.isNull() || end.isNull())
3253             return nil;
3254         return m_object->stringForVisiblePositionRange(VisiblePositionRange(start, end));
3255     }
3256
3257     if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"])
3258         return [self doAXAttributedStringForTextMarkerRange:textMarkerRange];
3259
3260     if ([attribute isEqualToString:@"AXTextMarkerRangeForUnorderedTextMarkers"]) {
3261         if ([array count] < 2)
3262             return nil;
3263
3264         id textMarker1 = [array objectAtIndex:0];
3265         id textMarker2 = [array objectAtIndex:1];
3266         if (!AXObjectIsTextMarker(textMarker1) || !AXObjectIsTextMarker(textMarker2))
3267             return nil;
3268
3269         VisiblePosition visiblePos1 = [self visiblePositionForTextMarker:(textMarker1)];
3270         VisiblePosition visiblePos2 = [self visiblePositionForTextMarker:(textMarker2)];
3271         VisiblePositionRange vpRange = m_object->visiblePositionRangeForUnorderedPositions(visiblePos1, visiblePos2);
3272         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3273     }
3274
3275     if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
3276         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3277         return [self textMarkerForVisiblePosition:m_object->nextVisiblePosition(visiblePos)];
3278     }
3279
3280     if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
3281         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3282         return [self textMarkerForVisiblePosition:m_object->previousVisiblePosition(visiblePos)];
3283     }
3284
3285     if ([attribute isEqualToString:@"AXLeftWordTextMarkerRangeForTextMarker"]) {
3286         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3287         VisiblePositionRange vpRange = m_object->positionOfLeftWord(visiblePos);
3288         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3289     }
3290
3291     if ([attribute isEqualToString:@"AXRightWordTextMarkerRangeForTextMarker"]) {
3292         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3293         VisiblePositionRange vpRange = m_object->positionOfRightWord(visiblePos);
3294         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3295     }
3296
3297     if ([attribute isEqualToString:@"AXLeftLineTextMarkerRangeForTextMarker"]) {
3298         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3299         VisiblePositionRange vpRange = m_object->leftLineVisiblePositionRange(visiblePos);
3300         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3301     }
3302
3303     if ([attribute isEqualToString:@"AXRightLineTextMarkerRangeForTextMarker"]) {
3304         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3305         VisiblePositionRange vpRange = m_object->rightLineVisiblePositionRange(visiblePos);
3306         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3307     }
3308
3309     if ([attribute isEqualToString:@"AXSentenceTextMarkerRangeForTextMarker"]) {
3310         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3311         VisiblePositionRange vpRange = m_object->sentenceForPosition(visiblePos);
3312         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3313     }
3314
3315     if ([attribute isEqualToString:@"AXParagraphTextMarkerRangeForTextMarker"]) {
3316         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3317         VisiblePositionRange vpRange = m_object->paragraphForPosition(visiblePos);
3318         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3319     }
3320
3321     if ([attribute isEqualToString:@"AXNextWordEndTextMarkerForTextMarker"]) {
3322         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3323         return [self textMarkerForVisiblePosition:m_object->nextWordEnd(visiblePos)];
3324     }
3325     
3326     if ([attribute isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
3327         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3328         return [self textMarkerForVisiblePosition:m_object->previousWordStart(visiblePos)];
3329     }
3330
3331     if ([attribute isEqualToString:@"AXNextLineEndTextMarkerForTextMarker"]) {
3332         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3333         return [self textMarkerForVisiblePosition:m_object->nextLineEndPosition(visiblePos)];
3334     }
3335
3336     if ([attribute isEqualToString:@"AXPreviousLineStartTextMarkerForTextMarker"]) {
3337         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3338         return [self textMarkerForVisiblePosition:m_object->previousLineStartPosition(visiblePos)];
3339     }
3340
3341     if ([attribute isEqualToString:@"AXNextSentenceEndTextMarkerForTextMarker"]) {
3342         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3343         return [self textMarkerForVisiblePosition:m_object->nextSentenceEndPosition(visiblePos)];
3344     }
3345
3346     if ([attribute isEqualToString:@"AXPreviousSentenceStartTextMarkerForTextMarker"]) {
3347         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3348         return [self textMarkerForVisiblePosition:m_object->previousSentenceStartPosition(visiblePos)];
3349     }
3350
3351     if ([attribute isEqualToString:@"AXNextParagraphEndTextMarkerForTextMarker"]) {
3352         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3353         return [self textMarkerForVisiblePosition:m_object->nextParagraphEndPosition(visiblePos)];
3354     }
3355
3356     if ([attribute isEqualToString:@"AXPreviousParagraphStartTextMarkerForTextMarker"]) {
3357         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3358         return [self textMarkerForVisiblePosition:m_object->previousParagraphStartPosition(visiblePos)];
3359     }
3360
3361     if ([attribute isEqualToString:@"AXStyleTextMarkerRangeForTextMarker"]) {
3362         VisiblePosition visiblePos = [self visiblePositionForTextMarker:(textMarker)];
3363         VisiblePositionRange vpRange = m_object->styleRangeForPosition(visiblePos);
3364         return [self textMarkerRangeFromVisiblePositions:vpRange.start endPosition:vpRange.end];
3365     }
3366
3367     if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {
3368         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3369         int length = m_object->lengthForVisiblePositionRange(visiblePosRange);
3370         if (length < 0)
3371             return nil;
3372         return [NSNumber numberWithInt:length];
3373     }
3374
3375     // Used only by DumpRenderTree (so far).
3376     if ([attribute isEqualToString:@"AXStartTextMarkerForTextMarkerRange"]) {
3377         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3378         return [self textMarkerForVisiblePosition:visiblePosRange.start];
3379     }
3380
3381     if ([attribute isEqualToString:@"AXEndTextMarkerForTextMarkerRange"]) {
3382         VisiblePositionRange visiblePosRange = [self visiblePositionRangeForTextMarkerRange:textMarkerRange];
3383         return [self textMarkerForVisiblePosition:visiblePosRange.end];
3384     }
3385     
3386     if (m_object->isAccessibilityTable()) {
3387         if ([attribute isEqualToString:NSAccessibilityCellForColumnAndRowParameterizedAttribute]) {
3388             if (array == nil || [array count] != 2)
3389                 return nil;
3390             AccessibilityTableCell* cell = static_cast<AccessibilityTable*>(m_object)->cellForColumnAndRow([[array objectAtIndex:0] unsignedIntValue], [[array objectAtIndex:1] unsignedIntValue]);
3391             if (!cell)
3392                 return nil;
3393             
3394             return cell->wrapper();
3395         }
3396     }
3397
3398     if (m_object->isTextControl()) {
3399         if ([attribute isEqualToString: (NSString *)kAXLineForIndexParameterizedAttribute]) {
3400             int lineNumber = m_object->doAXLineForIndex([number intValue]);
3401             if (lineNumber < 0)
3402                 return nil;
3403             return [NSNumber numberWithUnsignedInt:lineNumber];
3404         }
3405
3406         if ([attribute isEqualToString: (NSString *)kAXRangeForLineParameterizedAttribute]) {
3407             PlainTextRange textRange = m_object->doAXRangeForLine([number intValue]);
3408             return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3409         }
3410
3411         if ([attribute isEqualToString: (NSString*)kAXStringForRangeParameterizedAttribute]) {
3412             PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);
3413             return rangeSet ? (id)(m_object->doAXStringForRange(plainTextRange)) : nil;
3414         }
3415
3416         if ([attribute isEqualToString: (NSString*)kAXRangeForPositionParameterizedAttribute]) {
3417             if (!pointSet)
3418                 return nil;
3419             IntPoint webCorePoint = IntPoint(point);
3420             PlainTextRange textRange = m_object->doAXRangeForPosition(webCorePoint);
3421             return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3422         }
3423
3424         if ([attribute isEqualToString: (NSString*)kAXRangeForIndexParameterizedAttribute]) {
3425             PlainTextRange textRange = m_object->doAXRangeForIndex([number intValue]);
3426             return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3427         }
3428
3429         if ([attribute isEqualToString: (NSString*)kAXBoundsForRangeParameterizedAttribute]) {
3430             if (!rangeSet)
3431                 return nil;
3432             PlainTextRange plainTextRange = PlainTextRange(range.location, range.length);
3433             NSRect rect = m_object->doAXBoundsForRange(plainTextRange);
3434             return [NSValue valueWithRect:rect];
3435         }
3436
3437         if ([attribute isEqualToString: (NSString*)kAXRTFForRangeParameterizedAttribute])
3438             return rangeSet ? [self doAXRTFForRange:range] : nil;
3439
3440         if ([attribute isEqualToString: (NSString*)kAXAttributedStringForRangeParameterizedAttribute])
3441             return rangeSet ? [self doAXAttributedStringForRange:range] : nil;
3442
3443         if ([attribute isEqualToString: (NSString*)kAXStyleRangeForIndexParameterizedAttribute]) {
3444             PlainTextRange textRange = m_object->doAXStyleRangeForIndex([number intValue]);
3445             return [NSValue valueWithRange: NSMakeRange(textRange.start, textRange.length)];
3446         }
3447     }
3448
3449     // There are some parameters that super handles that are not explicitly returned by the list of the element's attributes.
3450     // In that case it must be passed to super. 
3451     return [super accessibilityAttributeValue:attribute forParameter:parameter];
3452 }
3453
3454 - (BOOL)accessibilitySupportsOverriddenAttributes
3455 {
3456     return YES;
3457 }
3458
3459 - (BOOL)accessibilityShouldUseUniqueId
3460 {
3461     // All AX object wrappers should use unique ID's because it's faster within AppKit to look them up.
3462     return YES;
3463 }
3464
3465 // API that AppKit uses for faster access
3466 - (NSUInteger)accessibilityIndexOfChild:(id)child
3467 {
3468     if (![self updateObjectBackingStore])
3469         return NSNotFound;
3470     
3471     // Tree objects return their rows as their children. We can use the original method
3472     // here, because we won't gain any speed up.
3473     if (m_object->isTree())
3474         return [super accessibilityIndexOfChild:child];
3475        
3476     const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
3477        
3478     if (children.isEmpty())
3479         return [[self renderWidgetChildren] indexOfObject:child];
3480     
3481     unsigned count = children.size();
3482     for (unsigned k = 0; k < count; ++k) {
3483         WebAccessibilityObjectWrapper* wrapper = children[k]->wrapper();
3484         if (wrapper == child || (children[k]->isAttachment() && [wrapper attachmentView] == child)) 
3485             return k;
3486     }
3487
3488     return NSNotFound;
3489 }
3490
3491 - (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute
3492 {
3493     if (![self updateObjectBackingStore])
3494         return 0;
3495     
3496     if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
3497         // Tree items object returns a different set of children than those that are in children()
3498         // because an AXOutline (the mac role is becomes) has some odd stipulations.
3499         if (m_object->isTree() || m_object->isTreeItem())
3500             return [[self accessibilityAttributeValue:NSAccessibilityChildrenAttribute] count];
3501         
3502         const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
3503         if (children.isEmpty())
3504             return [[self renderWidgetChildren] count];
3505         
3506         return children.size();
3507     }
3508     
3509     return [super accessibilityArrayAttributeCount:attribute];
3510 }
3511
3512 - (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount 
3513 {
3514     if (![self updateObjectBackingStore])
3515         return nil;
3516     
3517     if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
3518         if (m_object->children().isEmpty()) {
3519             NSArray *children = [self renderWidgetChildren];
3520             if (!children) 
3521                 return nil;
3522             
3523             NSUInteger childCount = [children count];
3524             if (index >= childCount)
3525                 return nil;
3526             
3527             NSUInteger arrayLength = min(childCount - index, maxCount);
3528             return [children subarrayWithRange:NSMakeRange(index, arrayLength)];
3529         } else if (m_object->isTree()) {
3530             // Tree objects return their rows as their children. We can use the original method in this case.
3531             return [super accessibilityArrayAttributeValues:attribute index:index maxCount:maxCount];
3532         }
3533         
3534         const AccessibilityObject::AccessibilityChildrenVector& children = m_object->children();
3535         unsigned childCount = children.size();
3536         if (index >= childCount)
3537             return nil;
3538