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