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