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