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