Reduce use of deprecatedCharacters in WebCore
[WebKit-https.git] / Source / WebCore / accessibility / ios / WebAccessibilityObjectWrapperIOS.mm
1 /*
2  * Copyright (C) 2008, 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  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "WebAccessibilityObjectWrapperIOS.h"
28
29 #if HAVE(ACCESSIBILITY) && PLATFORM(IOS)
30
31 #import "AccessibilityRenderObject.h"
32 #import "AccessibilityScrollView.h"
33 #import "AccessibilityTable.h"
34 #import "AccessibilityTableCell.h"
35 #import "Chrome.h"
36 #import "ChromeClient.h"
37 #import "Font.h"
38 #import "Frame.h"
39 #import "FrameSelection.h"
40 #import "FrameView.h"
41 #import "HitTestResult.h"
42 #import "HTMLFrameOwnerElement.h"
43 #import "HTMLInputElement.h"
44 #import "HTMLNames.h"
45 #import "IntRect.h"
46 #import "IntSize.h"
47 #import "Page.h"
48 #import "Range.h"
49 #import "RenderView.h"
50 #import "RuntimeApplicationChecksIOS.h"
51 #import "SVGNames.h"
52 #import "SVGElement.h"
53 #import "TextIterator.h"
54 #import "WAKScrollView.h"
55 #import "WAKView.h"
56 #import "WAKWindow.h"
57 #import "WebCoreThread.h"
58 #import "VisibleUnits.h"
59
60 #import <CoreText/CoreText.h>
61
62 @interface NSObject (AccessibilityPrivate)
63 - (void)_accessibilityUnregister;
64 - (NSString *)accessibilityLabel;
65 - (NSString *)accessibilityValue;
66 - (BOOL)isAccessibilityElement;
67 - (NSInteger)accessibilityElementCount;
68 - (id)accessibilityElementAtIndex:(NSInteger)index;
69 - (NSInteger)indexOfAccessibilityElement:(id)element;
70 @end
71
72 @interface WebAccessibilityObjectWrapper (AccessibilityPrivate)
73 - (id)_accessibilityWebDocumentView;
74 - (id)accessibilityContainer;
75 - (void)setAccessibilityLabel:(NSString *)label;
76 - (void)setAccessibilityValue:(NSString *)value;
77 - (BOOL)containsUnnaturallySegmentedChildren;
78 - (NSInteger)positionForTextMarker:(id)marker;
79 @end
80
81 @interface WAKView (iOSAccessibility)
82 - (BOOL)accessibilityIsIgnored;
83 @end
84
85 using namespace WebCore;
86 using namespace HTMLNames;
87
88 // These are tokens accessibility uses to denote attributes. 
89 static NSString * const UIAccessibilityTokenBlockquoteLevel = @"UIAccessibilityTokenBlockquoteLevel";
90 static NSString * const UIAccessibilityTokenHeadingLevel = @"UIAccessibilityTokenHeadingLevel";
91 static NSString * const UIAccessibilityTokenFontName = @"UIAccessibilityTokenFontName";
92 static NSString * const UIAccessibilityTokenFontFamily = @"UIAccessibilityTokenFontFamily";
93 static NSString * const UIAccessibilityTokenFontSize = @"UIAccessibilityTokenFontSize";
94 static NSString * const UIAccessibilityTokenBold = @"UIAccessibilityTokenBold";
95 static NSString * const UIAccessibilityTokenItalic = @"UIAccessibilityTokenItalic";
96 static NSString * const UIAccessibilityTokenUnderline = @"UIAccessibilityTokenUnderline";
97
98 static AccessibilityObjectWrapper* AccessibilityUnignoredAncestor(AccessibilityObjectWrapper *wrapper)
99 {
100     while (wrapper && ![wrapper isAccessibilityElement]) {
101         AccessibilityObject* object = [wrapper accessibilityObject];
102         if (!object)
103             break;
104         
105         if ([wrapper isAttachment] && ![[wrapper attachmentView] accessibilityIsIgnored])
106             break;
107             
108         AccessibilityObject* parentObject = object->parentObjectUnignored();
109         if (!parentObject)
110             break;
111
112         wrapper = parentObject->wrapper();
113     }
114     return wrapper;
115 }
116
117 #pragma mark Accessibility Text Marker
118
119 @interface WebAccessibilityTextMarker : NSObject
120 {
121     AXObjectCache* _cache;
122     TextMarkerData _textMarkerData;
123 }
124
125 + (WebAccessibilityTextMarker *)textMarkerWithVisiblePosition:(VisiblePosition&)visiblePos cache:(AXObjectCache*)cache;
126
127 @end
128
129 @implementation WebAccessibilityTextMarker
130
131 - (id)initWithTextMarker:(TextMarkerData *)data cache:(AXObjectCache*)cache
132 {
133     if (!(self = [super init]))
134         return nil;
135     
136     _cache = cache;
137     memcpy(&_textMarkerData, data, sizeof(TextMarkerData));
138     return self;
139 }
140
141 - (id)initWithData:(NSData *)data cache:(AXObjectCache*)cache
142 {
143     if (!(self = [super init]))
144         return nil;
145     
146     _cache = cache;
147     [data getBytes:&_textMarkerData length:sizeof(TextMarkerData)];
148     
149     return self;
150 }
151
152 // This is needed for external clients to be able to create a text marker without having a pointer to the cache.
153 - (id)initWithData:(NSData *)data accessibilityObject:(AccessibilityObjectWrapper *)wrapper
154 {
155     WebCore::AccessibilityObject* axObject = [wrapper accessibilityObject]; 
156     if (!axObject)
157         return nil;
158     
159     return [self initWithData:data cache:axObject->axObjectCache()];
160 }
161
162 + (WebAccessibilityTextMarker *)textMarkerWithVisiblePosition:(VisiblePosition&)visiblePos cache:(AXObjectCache*)cache
163 {
164     TextMarkerData textMarkerData;
165     cache->textMarkerDataForVisiblePosition(textMarkerData, visiblePos);
166     
167     return [[[WebAccessibilityTextMarker alloc] initWithTextMarker:&textMarkerData cache:cache] autorelease];
168 }
169
170 - (NSData *)dataRepresentation
171 {
172     return [NSData dataWithBytes:&_textMarkerData length:sizeof(TextMarkerData)];
173 }
174
175 - (VisiblePosition)visiblePosition
176 {
177     return _cache->visiblePositionForTextMarkerData(_textMarkerData);
178 }
179
180 - (NSString *)description
181 {
182     return [NSString stringWithFormat:@"[AXTextMarker %p] = node: %p offset: %d", self, _textMarkerData.node, _textMarkerData.offset];
183 }
184
185 @end
186
187 @implementation WebAccessibilityObjectWrapper
188
189 - (id)initWithAccessibilityObject:(AccessibilityObject*)axObject
190 {
191     self = [super initWithAccessibilityObject:axObject];
192     if (!self)
193         return nil;
194     
195     // Initialize to a sentinel value.
196     m_accessibilityTraitsFromAncestor = ULLONG_MAX;
197     m_isAccessibilityElement = -1;
198     
199     return self;
200 }
201
202 - (void)detach
203 {
204     // rdar://8798960 Make sure the object is gone early, so that anything _accessibilityUnregister 
205     // does can't call back into the render tree.
206     m_object = 0;
207
208     if ([self respondsToSelector:@selector(_accessibilityUnregister)])
209         [self _accessibilityUnregister];
210 }
211
212 - (void)dealloc
213 {
214     // We should have been detached before deallocated.
215     ASSERT(!m_object);
216     [super dealloc];
217 }
218
219 - (BOOL)_prepareAccessibilityCall
220 {
221     // rdar://7980318 if we start a call, then block in WebThreadLock(), then we're dealloced on another, thread, we could
222     // crash, so we should retain ourself for the duration of usage here.
223     [[self retain] autorelease];
224
225     WebThreadLock();
226     
227     // If we came back from our thread lock and we were detached, we will no longer have an m_object.
228     if (!m_object)
229         return NO;
230     
231     m_object->updateBackingStore();
232     if (!m_object)
233         return NO;
234     
235     return YES;
236 }
237
238 // These are here so that we don't have to import AXRuntime.
239 // The methods will be swizzled when the accessibility bundle is loaded.
240
241 - (uint64_t)_axLinkTrait { return (1 << 0); }
242 - (uint64_t)_axVisitedTrait { return (1 << 1); }
243 - (uint64_t)_axHeaderTrait { return (1 << 2); }
244 - (uint64_t)_axContainedByListTrait { return (1 << 3); }
245 - (uint64_t)_axContainedByTableTrait { return (1 << 4); }
246 - (uint64_t)_axContainedByLandmarkTrait { return (1 << 5); }
247 - (uint64_t)_axWebContentTrait { return (1 << 6); }
248 - (uint64_t)_axSecureTextFieldTrait { return (1 << 7); }
249 - (uint64_t)_axTextEntryTrait { return (1 << 8); }
250 - (uint64_t)_axHasTextCursorTrait { return (1 << 9); }
251 - (uint64_t)_axTextOperationsAvailableTrait { return (1 << 10); }
252 - (uint64_t)_axImageTrait { return (1 << 11); }
253 - (uint64_t)_axTabButtonTrait { return (1 << 12); }
254 - (uint64_t)_axButtonTrait { return (1 << 13); }
255 - (uint64_t)_axToggleTrait { return (1 << 14); }
256 - (uint64_t)_axPopupButtonTrait { return (1 << 15); }
257 - (uint64_t)_axStaticTextTrait { return (1 << 16); }
258 - (uint64_t)_axAdjustableTrait { return (1 << 17); }
259 - (uint64_t)_axMenuItemTrait { return (1 << 18); }
260 - (uint64_t)_axSelectedTrait { return (1 << 19); }
261 - (uint64_t)_axNotEnabledTrait { return (1 << 20); }
262 - (uint64_t)_axRadioButtonTrait { return (1 << 21); }
263
264 - (BOOL)accessibilityCanFuzzyHitTest
265 {
266     if (![self _prepareAccessibilityCall])
267         return nil;
268     
269     AccessibilityRole role = m_object->roleValue();
270     // Elements that can be returned when performing fuzzy hit testing.
271     switch (role) {
272     case ButtonRole:
273     case CheckBoxRole:
274     case ComboBoxRole:
275     case DisclosureTriangleRole:
276     case HeadingRole:
277     case ImageMapLinkRole:
278     case ImageRole:
279     case LinkRole:
280     case ListBoxRole:
281     case ListBoxOptionRole:
282     case MenuButtonRole:
283     case MenuItemRole:
284     case MenuItemCheckboxRole:
285     case MenuItemRadioRole:
286     case PopUpButtonRole:
287     case RadioButtonRole:
288     case ScrollBarRole:
289     case SliderRole:
290     case StaticTextRole:
291     case TabRole:
292     case TextFieldRole:
293         return !m_object->accessibilityIsIgnored();
294     default:
295         return false;
296     }
297 }
298
299 - (AccessibilityObjectWrapper *)accessibilityPostProcessHitTest:(CGPoint)point
300 {
301     UNUSED_PARAM(point);
302     // The UIKit accessibility wrapper will override this and perform the post process hit test.
303     return nil;
304 }
305
306 - (id)accessibilityHitTest:(CGPoint)point
307 {
308     if (![self _prepareAccessibilityCall])
309         return nil;
310     
311     // Try a fuzzy hit test first to find an accessible element.
312     RefPtr<AccessibilityObject> axObject;
313     {
314         AXAttributeCacheEnabler enableCache(m_object->axObjectCache());
315         axObject = m_object->accessibilityHitTest(IntPoint(point));
316     }
317
318     if (!axObject)
319         return nil;
320     
321     // If this is a good accessible object to return, no extra work is required.
322     if ([axObject->wrapper() accessibilityCanFuzzyHitTest])
323         return AccessibilityUnignoredAncestor(axObject->wrapper());
324     
325     // Check to see if we can post-process this hit test to find a better candidate.
326     AccessibilityObjectWrapper* wrapper = [axObject->wrapper() accessibilityPostProcessHitTest:point];
327     if (wrapper)
328         return AccessibilityUnignoredAncestor(wrapper);
329     
330     // Fall back to default behavior.
331     return AccessibilityUnignoredAncestor(axObject->wrapper());    
332 }
333
334 - (NSInteger)accessibilityElementCount
335 {
336     if (![self _prepareAccessibilityCall])
337         return nil;
338
339     AXAttributeCacheEnabler enableCache(m_object->axObjectCache());
340     if ([self isAttachment])
341         return [[self attachmentView] accessibilityElementCount];
342     
343     return m_object->children().size();
344 }
345
346 - (id)accessibilityElementAtIndex:(NSInteger)index
347 {
348     if (![self _prepareAccessibilityCall])
349         return nil;
350
351     AXAttributeCacheEnabler enableCache(m_object->axObjectCache());
352     if ([self isAttachment])
353         return [[self attachmentView] accessibilityElementAtIndex:index];
354     
355     const auto& children = m_object->children();
356     if (static_cast<unsigned>(index) >= children.size())
357         return nil;
358     
359     AccessibilityObjectWrapper* wrapper = children[index]->wrapper();
360     if (children[index]->isAttachment())
361         return [wrapper attachmentView];
362
363     return wrapper;
364 }
365
366 - (NSInteger)indexOfAccessibilityElement:(id)element
367 {
368     if (![self _prepareAccessibilityCall])
369         return NSNotFound;
370     
371     AXAttributeCacheEnabler enableCache(m_object->axObjectCache());
372     if ([self isAttachment])
373         return [[self attachmentView] indexOfAccessibilityElement:element];
374     
375     const auto& children = m_object->children();
376     unsigned count = children.size();
377     for (unsigned k = 0; k < count; ++k) {
378         AccessibilityObjectWrapper* wrapper = children[k]->wrapper();
379         if (wrapper == element || (children[k]->isAttachment() && [wrapper attachmentView] == element))
380             return k;
381     }
382     
383     return NSNotFound;
384 }
385
386 - (CGPathRef)_accessibilityPath
387 {
388     if (![self _prepareAccessibilityCall])
389         return NULL;
390
391     if (!m_object->supportsPath())
392         return NULL;
393     
394     Path path = m_object->elementPath();
395     if (path.isEmpty())
396         return NULL;
397     
398     return [self convertPathToScreenSpace:path];
399 }
400
401 - (NSString *)accessibilityLanguage
402 {
403     if (![self _prepareAccessibilityCall])
404         return nil;
405     
406     return m_object->language();
407 }
408
409 - (BOOL)_accessibilityIsLandmarkRole:(AccessibilityRole)role
410 {
411     switch (role) {
412         case LandmarkApplicationRole:
413         case LandmarkBannerRole:
414         case LandmarkComplementaryRole:
415         case LandmarkContentInfoRole:
416         case LandmarkMainRole:
417         case LandmarkNavigationRole:
418         case LandmarkSearchRole:
419             return YES;
420         default:
421             return NO;
422     }    
423 }
424
425 - (AccessibilityObjectWrapper*)_accessibilityListAncestor
426 {
427     for (AccessibilityObject* parent = m_object->parentObject(); parent != nil; parent = parent->parentObject()) {
428         AccessibilityRole role = parent->roleValue();
429         if (role == ListRole || role == ListBoxRole)
430             return parent->wrapper();
431     }
432     
433     return nil;
434 }
435
436 - (AccessibilityObjectWrapper*)_accessibilityLandmarkAncestor
437 {
438     for (AccessibilityObject* parent = m_object->parentObject(); parent != nil; parent = parent->parentObject()) {
439         if ([self _accessibilityIsLandmarkRole:parent->roleValue()])
440             return parent->wrapper();
441     }
442
443     return nil;
444 }
445
446 - (AccessibilityObjectWrapper*)_accessibilityTableAncestor
447 {
448     for (AccessibilityObject* parent = m_object->parentObject(); parent != nil; parent = parent->parentObject()) {
449         if (parent->roleValue() == TableRole)
450             return parent->wrapper();   
451     }
452     
453     return nil;
454 }
455
456 - (uint64_t)_accessibilityTraitsFromAncestors
457 {
458     uint64_t traits = 0;
459     AccessibilityRole role = m_object->roleValue();
460     
461     // Trait information also needs to be gathered from the parents above the object.
462     // The parentObject is needed instead of the unignoredParentObject, because a table might be ignored, but information still needs to be gathered from it.    
463     for (AccessibilityObject* parent = m_object->parentObject(); parent != nil; parent = parent->parentObject()) {
464         AccessibilityRole parentRole = parent->roleValue();
465         if (parentRole == WebAreaRole)
466             break;
467         
468         switch (parentRole) {
469             case LinkRole:
470             case WebCoreLinkRole:
471                 traits |= [self _axLinkTrait];
472                 if (parent->isVisited())
473                     traits |= [self _axVisitedTrait];
474                 break;
475             case HeadingRole:
476             {
477                 traits |= [self _axHeaderTrait];
478                 // If this object has the header trait, we should set the value
479                 // to the heading level. If it was a static text element, we need to store
480                 // the value as the label, because the heading level needs to the value.
481                 AccessibilityObjectWrapper* wrapper = parent->wrapper();
482                 if (role == StaticTextRole) 
483                     [self setAccessibilityLabel:m_object->stringValue()];                
484                 [self setAccessibilityValue:[wrapper accessibilityValue]];
485                 break;
486             }
487             case ListBoxRole:
488             case ListRole:
489                 traits |= [self _axContainedByListTrait];
490                 break;
491             case TableRole:
492                 traits |= [self _axContainedByTableTrait];
493                 break;
494             default:
495                 if ([self _accessibilityIsLandmarkRole:parentRole])
496                     traits |= [self _axContainedByLandmarkTrait];
497                 break;
498         }
499     }
500     
501     return traits;
502 }
503
504 - (uint64_t)accessibilityTraits
505 {
506     if (![self _prepareAccessibilityCall])
507         return 0;
508     
509     AccessibilityRole role = m_object->roleValue();
510     uint64_t traits = [self _axWebContentTrait];
511     switch (role) {
512         case LinkRole:
513         case WebCoreLinkRole:
514             traits |= [self _axLinkTrait];
515             if (m_object->isVisited())
516                 traits |= [self _axVisitedTrait];
517             break;
518         // TextFieldRole is intended to fall through to TextAreaRole, in order to pick up the text entry and text cursor traits.
519         case TextFieldRole:
520             if (m_object->isPasswordField())
521                 traits |= [self _axSecureTextFieldTrait];
522             FALLTHROUGH;
523         case TextAreaRole:
524             traits |= [self _axTextEntryTrait];
525             if (m_object->isFocused())
526                 traits |= ([self _axHasTextCursorTrait] | [self _axTextOperationsAvailableTrait]);
527             break;
528         case ImageRole:
529             traits |= [self _axImageTrait];
530             break;
531         case TabRole:
532             traits |= [self _axTabButtonTrait];
533             break;
534         case ButtonRole:
535             traits |= [self _axButtonTrait];
536             if (m_object->isPressed())
537                 traits |= [self _axToggleTrait];
538             break;
539         case PopUpButtonRole:
540             traits |= [self _axPopupButtonTrait];
541             break;
542         case RadioButtonRole:
543             traits |= [self _axRadioButtonTrait] | [self _axToggleTrait];
544             break;
545         case CheckBoxRole:
546             traits |= ([self _axButtonTrait] | [self _axToggleTrait]);
547             break;
548         case HeadingRole:
549             traits |= [self _axHeaderTrait];
550             break;
551         case StaticTextRole:
552             traits |= [self _axStaticTextTrait];
553             break;
554         case SliderRole:
555             traits |= [self _axAdjustableTrait];
556             break;
557         case MenuButtonRole:
558         case MenuItemRole:
559         case MenuItemCheckboxRole:
560         case MenuItemRadioRole:
561             traits |= [self _axMenuItemTrait];
562             break;
563         default:
564             break;
565     }
566
567     if (m_object->isSelected())
568         traits |= [self _axSelectedTrait];
569
570     if (!m_object->isEnabled())
571         traits |= [self _axNotEnabledTrait];
572     
573     if (m_accessibilityTraitsFromAncestor == ULLONG_MAX)
574         m_accessibilityTraitsFromAncestor = [self _accessibilityTraitsFromAncestors];
575     
576     traits |= m_accessibilityTraitsFromAncestor;
577
578     return traits;
579 }
580
581 - (BOOL)isSVGGroupElement
582 {
583     // If an SVG group element has a title, it should be an accessible element on iOS.
584     Node* node = m_object->node();
585     if (node && node->hasTagName(SVGNames::gTag) && [[self accessibilityLabel] length] > 0)
586         return YES;
587     
588     return NO;
589 }
590
591 - (BOOL)determineIsAccessibilityElement
592 {
593     if (!m_object)
594         return false;
595     
596     // Honor when something explicitly makes this an element (super will contain that logic) 
597     if ([super isAccessibilityElement])
598         return YES;
599     
600     m_object->updateBackingStore();
601     
602     switch (m_object->roleValue()) {
603         case TextFieldRole:
604         case TextAreaRole:
605         case ButtonRole:
606         case PopUpButtonRole:
607         case CheckBoxRole:
608         case RadioButtonRole:
609         case SliderRole:
610         case MenuButtonRole:
611         case ValueIndicatorRole:
612         case ImageRole:
613         case ProgressIndicatorRole:
614         case MenuItemRole:
615         case IncrementorRole:
616         case ComboBoxRole:
617         case DisclosureTriangleRole:
618         case ImageMapRole:
619         case ListMarkerRole:
620         case ListBoxOptionRole:
621         case TabRole:
622         case DocumentMathRole:
623             return true;
624         case StaticTextRole:
625         {
626             // Many text elements only contain a space.
627             if (![[[self accessibilityLabel] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] length])
628                 return false;
629
630             // Text elements that are just pieces of links or headers should not be exposed.
631             if ([AccessibilityUnignoredAncestor([self accessibilityContainer]) containsUnnaturallySegmentedChildren])
632                 return false;
633             return true;
634         }
635             
636         // Don't expose headers as elements; instead expose their children as elements, with the header trait (unless they have no children)
637         case HeadingRole:
638             if (![self accessibilityElementCount])
639                 return true;
640             return false;
641             
642         // Links can sometimes be elements (when they only contain static text or don't contain anything).
643         // They should not be elements when containing text and other types.
644         case WebCoreLinkRole:
645         case LinkRole:
646             if ([self containsUnnaturallySegmentedChildren] || ![self accessibilityElementCount])
647                 return true;
648             return false;
649         case GroupRole:
650             if ([self isSVGGroupElement])
651                 return true;
652             FALLTHROUGH;
653         // All other elements are ignored on the iphone.
654         default:
655         case UnknownRole:
656         case TabGroupRole:
657         case ScrollAreaRole:
658         case TableRole:
659         case ApplicationRole:
660         case RadioGroupRole:
661         case ListRole:
662         case ListBoxRole:
663         case ScrollBarRole:
664         case MenuBarRole:
665         case MenuRole:
666         case ColumnRole:
667         case RowRole:
668         case ToolbarRole:
669         case BusyIndicatorRole:
670         case WindowRole:
671         case DrawerRole:
672         case SystemWideRole:
673         case OutlineRole:
674         case BrowserRole:
675         case SplitGroupRole:
676         case SplitterRole:
677         case ColorWellRole:
678         case GrowAreaRole:
679         case SheetRole:
680         case HelpTagRole:
681         case MatteRole:
682         case RulerRole:
683         case RulerMarkerRole:
684         case GridRole:
685         case WebAreaRole:
686             return false;
687     }
688 }
689
690 - (BOOL)isAccessibilityElement
691 {
692     if (![self _prepareAccessibilityCall])
693         return NO;
694     
695     if (m_isAccessibilityElement == -1)
696         m_isAccessibilityElement = [self determineIsAccessibilityElement];
697     
698     return m_isAccessibilityElement;
699 }
700
701 - (BOOL)stringValueShouldBeUsedInLabel
702 {
703     if (m_object->isTextControl())
704         return NO;
705     if (m_object->roleValue() == PopUpButtonRole)
706         return NO;
707     if (m_object->isFileUploadButton())
708         return NO;
709
710     return YES;
711 }
712
713 - (BOOL)fileUploadButtonReturnsValueInTitle
714 {
715     return NO;
716 }
717
718 static void appendStringToResult(NSMutableString *result, NSString *string)
719 {
720     ASSERT(result);
721     if (![string length])
722         return;
723     if ([result length])
724         [result appendString:@", "];
725     [result appendString:string];
726 }
727
728 - (CGFloat)_accessibilityMinValue
729 {
730     return m_object->minValueForRange();
731 }
732
733 - (CGFloat)_accessibilityMaxValue
734 {
735     return m_object->maxValueForRange();
736 }
737
738 - (NSString *)accessibilityLabel
739 {
740     if (![self _prepareAccessibilityCall])
741         return nil;
742
743     // check if the label was overriden
744     NSString *label = [super accessibilityLabel];
745     if (label)
746         return label;
747
748     // iOS doesn't distinguish between a title and description field,
749     // so concatentation will yield the best result.
750     NSString *axTitle = [self accessibilityTitle];
751     NSString *axDescription = [self accessibilityDescription];
752     NSString *landmarkDescription = [self ariaLandmarkRoleDescription];
753
754     NSMutableString *result = [NSMutableString string];
755
756     appendStringToResult(result, axTitle);
757     appendStringToResult(result, axDescription);
758     if ([self stringValueShouldBeUsedInLabel]) {
759         NSString *valueLabel = m_object->stringValue();
760         valueLabel = [valueLabel stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
761         appendStringToResult(result, valueLabel);
762     }
763     appendStringToResult(result, landmarkDescription);
764     
765     return [result length] ? result : nil;
766 }
767
768 - (AccessibilityTableCell*)tableCellParent
769 {
770     // Find if this element is in a table cell.
771     AccessibilityObject* cell = 0;
772     for (cell = m_object; cell && !cell->isTableCell(); cell = cell->parentObject()) 
773     { }
774     
775     if (!cell)
776         return 0;
777
778     return static_cast<AccessibilityTableCell*>(cell);
779 }
780
781 - (AccessibilityTable*)tableParent
782 {
783     // Find if the parent table for the table cell.
784     AccessibilityObject* parentTable = 0;
785     for (parentTable = m_object; parentTable && !parentTable->isDataTable(); parentTable = parentTable->parentObject()) 
786     { }
787     
788     if (!parentTable)
789         return 0;
790     
791     return static_cast<AccessibilityTable*>(parentTable);
792 }
793
794 - (id)accessibilityTitleElement
795 {
796     if (![self _prepareAccessibilityCall])
797         return nil;
798
799     AccessibilityObject* titleElement = m_object->titleUIElement();
800     if (titleElement)
801         return titleElement->wrapper();
802
803     return nil;
804 }
805
806 // Meant to return row or column headers (or other things as the future permits).
807 - (NSArray *)accessibilityHeaderElements
808 {
809     if (![self _prepareAccessibilityCall])
810         return nil;
811
812     AccessibilityTableCell* tableCell = [self tableCellParent];
813     if (!tableCell)
814         return nil;
815     
816     AccessibilityTable* table = [self tableParent];
817     if (!table)
818         return nil;
819     
820     // Get the row and column range, so we can use them to find the headers.
821     std::pair<unsigned, unsigned> rowRange;
822     std::pair<unsigned, unsigned> columnRange;
823     tableCell->rowIndexRange(rowRange);
824     tableCell->columnIndexRange(columnRange);
825     
826     AccessibilityObject::AccessibilityChildrenVector rowHeaders;
827     AccessibilityObject::AccessibilityChildrenVector columnHeaders;
828     table->rowHeaders(rowHeaders);
829     table->columnHeaders(columnHeaders);
830     
831     NSMutableArray *headers = [NSMutableArray array];
832     
833     unsigned columnRangeIndex = static_cast<unsigned>(columnRange.first);
834     if (columnRangeIndex < columnHeaders.size()) {
835         RefPtr<AccessibilityObject> columnHeader = columnHeaders[columnRange.first];
836         AccessibilityObjectWrapper* wrapper = columnHeader->wrapper();
837         if (wrapper)
838             [headers addObject:wrapper];
839     }
840
841     unsigned rowRangeIndex = static_cast<unsigned>(rowRange.first);
842     if (rowRangeIndex < rowHeaders.size()) {
843         RefPtr<AccessibilityObject> rowHeader = rowHeaders[rowRange.first];
844         AccessibilityObjectWrapper* wrapper = rowHeader->wrapper();
845         if (wrapper)
846             [headers addObject:wrapper];
847     }
848         
849     return headers;
850 }
851
852 - (id)accessibilityElementForRow:(NSInteger)row andColumn:(NSInteger)column
853 {
854     if (![self _prepareAccessibilityCall])
855         return nil;
856
857     AccessibilityTable* table = [self tableParent];
858     if (!table)
859         return nil;
860
861     AccessibilityTableCell* cell = table->cellForColumnAndRow(column, row);
862     if (!cell)
863         return nil;
864     return cell->wrapper();
865 }
866
867 - (NSRange)accessibilityRowRange
868 {
869     if (![self _prepareAccessibilityCall])
870         return NSMakeRange(NSNotFound, 0);
871
872     if (m_object->isRadioButton()) {
873         AccessibilityObject::AccessibilityChildrenVector radioButtonSiblings;
874         m_object->linkedUIElements(radioButtonSiblings);
875         if (radioButtonSiblings.size() <= 1)
876             return NSMakeRange(NSNotFound, 0);
877         
878         return NSMakeRange(radioButtonSiblings.find(m_object), radioButtonSiblings.size());
879     }
880     
881     AccessibilityTableCell* tableCell = [self tableCellParent];
882     if (!tableCell)
883         return NSMakeRange(NSNotFound, 0);
884     
885     std::pair<unsigned, unsigned> rowRange;
886     tableCell->rowIndexRange(rowRange);
887     return NSMakeRange(rowRange.first, rowRange.second);
888 }
889
890 - (NSRange)accessibilityColumnRange
891 {
892     if (![self _prepareAccessibilityCall])
893         return NSMakeRange(NSNotFound, 0);
894
895     AccessibilityTableCell* tableCell = [self tableCellParent];
896     if (!tableCell)
897         return NSMakeRange(NSNotFound, 0);
898     
899     std::pair<unsigned, unsigned> columnRange;
900     tableCell->columnIndexRange(columnRange);
901     return NSMakeRange(columnRange.first, columnRange.second);
902 }
903
904 - (NSString *)accessibilityPlaceholderValue
905 {
906     if (![self _prepareAccessibilityCall])
907         return nil;
908
909     return m_object->placeholderValue();
910 }
911
912 - (NSString *)accessibilityValue
913 {
914     if (![self _prepareAccessibilityCall])
915         return nil;
916     
917     // check if the value was overriden
918     NSString *value = [super accessibilityValue];
919     if (value)
920         return value;
921     
922     if (m_object->isCheckboxOrRadio()) {
923         switch (m_object->checkboxOrRadioValue()) {
924         case ButtonStateOff:
925             return [NSString stringWithFormat:@"%d", 0];
926         case ButtonStateOn:
927             return [NSString stringWithFormat:@"%d", 1];
928         case ButtonStateMixed:
929             return [NSString stringWithFormat:@"%d", 2];
930         }
931         ASSERT_NOT_REACHED();
932         return [NSString stringWithFormat:@"%d", 0];
933     }
934     
935     if (m_object->isButton() && m_object->isPressed())
936         return [NSString stringWithFormat:@"%d", 1];
937
938     // rdar://8131388 WebKit should expose the same info as UIKit for its password fields.
939     if (m_object->isPasswordField()) {
940         int passwordLength = m_object->accessibilityPasswordFieldLength();
941         NSMutableString* string = [NSMutableString string];
942         for (int k = 0; k < passwordLength; ++k)
943             [string appendString:@"•"];
944         return string;
945     }
946     
947     // A text control should return its text data as the axValue (per iPhone AX API).
948     if (![self stringValueShouldBeUsedInLabel])
949         return m_object->stringValue();
950     
951     if (m_object->isProgressIndicator() || m_object->isSlider()) {
952         // Prefer a valueDescription if provided by the author (through aria-valuetext).
953         String valueDescription = m_object->valueDescription();
954         if (!valueDescription.isEmpty())
955             return valueDescription;
956
957         return [NSString stringWithFormat:@"%.2f", m_object->valueForRange()];
958     }
959
960     if (m_object->isHeading())
961         return [NSString stringWithFormat:@"%d", m_object->headingLevel()];
962     
963     return nil;
964 }
965
966 - (BOOL)accessibilityIsComboBox
967 {
968     if (![self _prepareAccessibilityCall])
969         return NO;
970
971     return m_object->roleValue() == ComboBoxRole;
972 }
973
974 - (NSString *)accessibilityHint
975 {
976     if (![self _prepareAccessibilityCall])
977         return nil;
978
979     return [self accessibilityHelpText];
980 }
981
982 - (NSURL *)accessibilityURL
983 {
984     if (![self _prepareAccessibilityCall])
985         return nil;
986     
987     URL url = m_object->url();
988     if (url.isNull())
989         return nil;
990     return (NSURL*)url;
991 }
992
993 - (CGPoint)convertPointToScreenSpace:(FloatPoint &)point
994 {
995     if (!m_object)
996         return CGPointZero;
997     
998     CGPoint cgPoint = CGPointMake(point.x(), point.y());
999     
1000     FrameView* frameView = m_object->documentFrameView();
1001     WAKView* documentView = frameView ? frameView->documentView() : nullptr;
1002     if (documentView) {
1003         cgPoint = [documentView convertPoint:cgPoint toView:nil];
1004
1005         // we need the web document view to give us our final screen coordinates
1006         // because that can take account of the scroller
1007         id webDocument = [self _accessibilityWebDocumentView];
1008         if (webDocument)
1009             cgPoint = [webDocument convertPoint:cgPoint toView:nil];
1010     }
1011     else {
1012         // Find the appropriate scroll view to use to convert the contents to the window.
1013         ScrollView* scrollView = 0;
1014         AccessibilityObject* parent = 0;
1015         for (parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1016             if (parent->isAccessibilityScrollView()) {
1017                 scrollView = toAccessibilityScrollView(parent)->scrollView();
1018                 break;
1019             }
1020         }
1021         
1022         IntPoint intPoint = flooredIntPoint(point);
1023         if (scrollView)
1024             intPoint = scrollView->contentsToRootView(intPoint);
1025         
1026         Page* page = m_object->page();
1027         
1028         // If we have an empty chrome client (like SVG) then we should use the page
1029         // of the scroll view parent to help us get to the screen rect.
1030         if (parent && page && page->chrome().client().isEmptyChromeClient())
1031             page = parent->page();
1032         
1033         if (page) {
1034             IntRect rect = IntRect(intPoint, IntSize(0, 0));
1035             intPoint = page->chrome().rootViewToScreen(rect).location();
1036         }
1037         
1038         cgPoint = (CGPoint)intPoint;
1039     }
1040     
1041     return cgPoint;
1042 }
1043
1044 - (CGRect)convertRectToScreenSpace:(IntRect &)rect
1045 {
1046     if (!m_object)
1047         return CGRectZero;
1048     
1049     CGSize size = CGSizeMake(rect.size().width(), rect.size().height());
1050     CGPoint point = CGPointMake(rect.x(), rect.y());
1051     
1052     CGRect frame = CGRectMake(point.x, point.y, size.width, size.height);
1053     
1054     FrameView* frameView = m_object->documentFrameView();
1055     WAKView* documentView = frameView ? frameView->documentView() : nil;
1056     if (documentView) {
1057         frame = [documentView convertRect:frame toView:nil];
1058         
1059         // we need the web document view to give us our final screen coordinates
1060         // because that can take account of the scroller
1061         id webDocument = [self _accessibilityWebDocumentView];
1062         if (webDocument)
1063             frame = [webDocument convertRect:frame toView:nil];
1064         
1065     } else {
1066         // Find the appropriate scroll view to use to convert the contents to the window.
1067         ScrollView* scrollView = 0;
1068         AccessibilityObject* parent = 0;
1069         for (parent = m_object->parentObject(); parent; parent = parent->parentObject()) {
1070             if (parent->isAccessibilityScrollView()) {
1071                 scrollView = toAccessibilityScrollView(parent)->scrollView();
1072                 break;
1073             }
1074         }
1075         
1076         if (scrollView)
1077             rect = scrollView->contentsToRootView(rect);
1078         
1079         Page* page = m_object->page();
1080         
1081         // If we have an empty chrome client (like SVG) then we should use the page
1082         // of the scroll view parent to help us get to the screen rect.
1083         if (parent && page && page->chrome().client().isEmptyChromeClient())
1084             page = parent->page();
1085         
1086         if (page)
1087             rect = page->chrome().rootViewToScreen(rect);
1088         
1089         frame = (CGRect)rect;
1090     }
1091     
1092     return frame;
1093 }
1094
1095 // Used by UIKit accessibility bundle to help determine distance during a hit-test.
1096 - (CGRect)accessibilityElementRect
1097 {
1098     if (![self _prepareAccessibilityCall])
1099         return CGRectZero;
1100     
1101     LayoutRect rect = m_object->elementRect();
1102     return CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
1103 }
1104
1105 // The "center point" is where VoiceOver will "press" an object. This may not be the actual
1106 // center of the accessibilityFrame
1107 - (CGPoint)accessibilityActivationPoint
1108 {
1109     if (![self _prepareAccessibilityCall])
1110         return CGPointZero;
1111     
1112     IntRect rect = pixelSnappedIntRect(m_object->boundingBoxRect());
1113     CGRect cgRect = [self convertRectToScreenSpace:rect];
1114     return CGPointMake(CGRectGetMidX(cgRect), CGRectGetMidY(cgRect));
1115 }
1116
1117 - (CGRect)accessibilityFrame
1118 {
1119     if (![self _prepareAccessibilityCall])
1120         return CGRectZero;
1121     
1122     IntRect rect = pixelSnappedIntRect(m_object->elementRect());
1123     return [self convertRectToScreenSpace:rect];
1124 }
1125
1126 // Checks whether a link contains only static text and images (and has been divided unnaturally by <spans> and other nefarious mechanisms).
1127 - (BOOL)containsUnnaturallySegmentedChildren
1128 {
1129     if (!m_object)
1130         return NO;
1131     
1132     AccessibilityRole role = m_object->roleValue();
1133     if (role != LinkRole && role != WebCoreLinkRole)
1134         return NO;
1135     
1136     const auto& children = m_object->children();
1137     unsigned childrenSize = children.size();
1138
1139     // If there's only one child, then it doesn't have segmented children. 
1140     if (childrenSize == 1)
1141         return NO;
1142     
1143     for (unsigned i = 0; i < childrenSize; ++i) {
1144         AccessibilityRole role = children[i]->roleValue();
1145         if (role != StaticTextRole && role != ImageRole && role != GroupRole)
1146             return NO;
1147     }
1148     
1149     return YES;
1150 }
1151
1152 - (id)accessibilityContainer
1153 {
1154     if (![self _prepareAccessibilityCall])
1155         return nil;
1156
1157     AXAttributeCacheEnabler enableCache(m_object->axObjectCache());
1158     
1159     // As long as there's a parent wrapper, that's the correct chain to climb.
1160     AccessibilityObject* parent = m_object->parentObjectUnignored(); 
1161     if (parent)
1162         return parent->wrapper();
1163
1164     // The only object without a parent wrapper should be a scroll view.
1165     ASSERT(m_object->isAccessibilityScrollView());
1166     
1167     // Verify this is the top document. If not, we might need to go through the platform widget.
1168     FrameView* frameView = m_object->documentFrameView();
1169     Document* document = m_object->document();
1170     if (document && frameView && document != &document->topDocument())
1171         return frameView->platformWidget();
1172     
1173     // The top scroll view's parent is the web document view.
1174     return [self _accessibilityWebDocumentView];
1175 }
1176
1177 - (id)accessibilityFocusedUIElement
1178 {
1179     if (![self _prepareAccessibilityCall])
1180         return nil;
1181     
1182     AccessibilityObject* focusedObj = m_object->focusedUIElement();
1183     
1184     if (!focusedObj)
1185         return nil;
1186     
1187     return focusedObj->wrapper();
1188 }
1189
1190 - (id)_accessibilityWebDocumentView
1191 {
1192     if (![self _prepareAccessibilityCall])
1193         return nil;
1194
1195     // This method performs the crucial task of connecting to the UIWebDocumentView.
1196     // This is needed to correctly calculate the screen position of the AX object.
1197     static Class webViewClass = nil;
1198     if (!webViewClass)
1199         webViewClass = NSClassFromString(@"WebView");
1200
1201     if (!webViewClass)
1202         return nil;
1203     
1204     FrameView* frameView = m_object->documentFrameView();
1205
1206     if (!frameView)
1207         return nil;
1208     
1209     // If this is the top level frame, the UIWebDocumentView should be returned.
1210     id parentView = frameView->documentView();
1211     while (parentView && ![parentView isKindOfClass:webViewClass])
1212         parentView = [parentView superview];
1213     
1214     // The parentView should have an accessibilityContainer, if the UIKit accessibility bundle was loaded. 
1215     // The exception is DRT, which tests accessibility without the entire system turning accessibility on. Hence,
1216     // this check should be valid for everything except DRT.
1217     ASSERT([parentView accessibilityContainer] || applicationIsDumpRenderTree());
1218     
1219     return [parentView accessibilityContainer];
1220 }
1221
1222 - (NSArray *)_accessibilityNextElementsWithCount:(UInt32)count
1223 {    
1224     if (![self _prepareAccessibilityCall])
1225         return nil;
1226     
1227     return [[self _accessibilityWebDocumentView] _accessibilityNextElementsWithCount:count];
1228 }
1229
1230 - (NSArray *)_accessibilityPreviousElementsWithCount:(UInt32)count
1231 {
1232     if (![self _prepareAccessibilityCall])
1233         return nil;
1234     
1235     return [[self _accessibilityWebDocumentView] _accessibilityPreviousElementsWithCount:count];
1236 }
1237
1238 - (BOOL)accessibilityRequired
1239 {
1240     if (![self _prepareAccessibilityCall])
1241         return NO;
1242
1243     return m_object->isRequired();
1244 }
1245
1246 - (NSArray *)accessibilityFlowToElements
1247 {
1248     if (![self _prepareAccessibilityCall])
1249         return nil;
1250     
1251     AccessibilityObject::AccessibilityChildrenVector children;
1252     m_object->ariaFlowToElements(children);
1253     
1254     unsigned length = children.size();
1255     NSMutableArray* array = [NSMutableArray arrayWithCapacity:length];
1256     for (unsigned i = 0; i < length; ++i) {
1257         AccessibilityObjectWrapper* wrapper = children[i]->wrapper();
1258         ASSERT(wrapper);
1259         if (!wrapper)
1260             continue;
1261
1262         if (children[i]->isAttachment() && [wrapper attachmentView])
1263             [array addObject:[wrapper attachmentView]];
1264         else
1265             [array addObject:wrapper];
1266     }
1267     return array;
1268 }
1269
1270 - (id)accessibilityLinkedElement
1271 {
1272     if (![self _prepareAccessibilityCall])
1273         return nil;
1274     
1275     // If this static text inside of a link, it should use its parent's linked element.
1276     AccessibilityObject* element = m_object;
1277     if (m_object->roleValue() == StaticTextRole && m_object->parentObjectUnignored()->isLink())
1278         element = m_object->parentObjectUnignored();
1279     
1280     AccessibilityObject::AccessibilityChildrenVector children;
1281     element->linkedUIElements(children);
1282     if (children.size() == 0)
1283         return nil;
1284     
1285     return children[0]->wrapper();
1286 }
1287
1288
1289 - (BOOL)isAttachment
1290 {
1291     if (!m_object)
1292         return NO;
1293     
1294     return m_object->isAttachment();
1295 }
1296
1297 - (void)_accessibilityActivate
1298 {
1299     if (![self _prepareAccessibilityCall])
1300         return;
1301
1302     m_object->press();
1303 }
1304
1305 - (id)attachmentView
1306 {
1307     if (![self _prepareAccessibilityCall])
1308         return nil;
1309
1310     ASSERT([self isAttachment]);
1311     Widget* widget = m_object->widgetForAttachmentView();
1312     if (!widget)
1313         return nil;
1314     return widget->platformWidget();    
1315 }
1316
1317 static RenderObject* rendererForView(WAKView* view)
1318 {
1319     if (![view conformsToProtocol:@protocol(WebCoreFrameView)])
1320         return 0;
1321     
1322     WAKView<WebCoreFrameView>* frameView = (WAKView<WebCoreFrameView>*)view;
1323     Frame* frame = [frameView _web_frame];
1324     if (!frame)
1325         return 0;
1326     
1327     Node* node = frame->document()->ownerElement();
1328     if (!node)
1329         return 0;
1330     
1331     return node->renderer();
1332 }
1333
1334 - (id)_accessibilityParentForSubview:(id)subview
1335 {   
1336     RenderObject* renderer = rendererForView(subview);
1337     if (!renderer)
1338         return nil;
1339     
1340     AccessibilityObject* obj = renderer->document().axObjectCache()->getOrCreate(renderer);
1341     if (obj)
1342         return obj->parentObjectUnignored()->wrapper();
1343     return nil;
1344 }
1345
1346 - (void)postFocusChangeNotification
1347 {
1348     // The UIKit accessibility wrapper will override and post appropriate notification.
1349 }
1350
1351 - (void)postSelectedTextChangeNotification
1352 {
1353     // The UIKit accessibility wrapper will override and post appropriate notification.    
1354 }
1355
1356 - (void)postLayoutChangeNotification
1357 {
1358     // The UIKit accessibility wrapper will override and post appropriate notification.        
1359 }
1360
1361 - (void)postLiveRegionChangeNotification
1362 {
1363     // The UIKit accessibility wrapper will override and post appropriate notification.    
1364 }
1365
1366 - (void)postLoadCompleteNotification
1367 {
1368     // The UIKit accessibility wrapper will override and post appropriate notification.    
1369 }
1370
1371 - (void)postChildrenChangedNotification
1372 {
1373     // The UIKit accessibility wrapper will override and post appropriate notification.    
1374 }
1375
1376 - (void)postInvalidStatusChangedNotification
1377 {
1378     // The UIKit accessibility wrapper will override and post appropriate notification.        
1379 }
1380
1381 - (void)accessibilityElementDidBecomeFocused
1382 {
1383     if (![self _prepareAccessibilityCall])
1384         return;
1385     
1386     // The focused VoiceOver element might be the text inside a link.
1387     // In those cases we should focus on the link itself.
1388     for (AccessibilityObject* object = m_object; object != nil; object = object->parentObject()) {
1389         if (object->roleValue() == WebAreaRole)
1390             break;
1391
1392         if (object->canSetFocusAttribute()) {
1393             object->setFocused(true);
1394             break;
1395         }
1396     }
1397 }
1398
1399 - (void)accessibilityModifySelection:(TextGranularity)granularity increase:(BOOL)increase
1400 {
1401     if (![self _prepareAccessibilityCall])
1402         return;
1403     
1404     FrameSelection& frameSelection = m_object->document()->frame()->selection();
1405     VisibleSelection selection = m_object->selection();
1406     VisiblePositionRange range = m_object->visiblePositionRange();
1407     
1408     // Before a selection with length exists, the cursor position needs to move to the right starting place.
1409     // That should be the beginning of this element (range.start). However, if the cursor is already within the 
1410     // range of this element (the cursor is represented by selection), then the cursor does not need to move.
1411     if (frameSelection.isNone() && (selection.visibleStart() < range.start || selection.visibleEnd() > range.end))
1412         frameSelection.moveTo(range.start, UserTriggered);
1413     
1414     frameSelection.modify(FrameSelection::AlterationExtend, (increase) ? DirectionRight : DirectionLeft, granularity, UserTriggered);
1415 }
1416
1417 - (void)accessibilityIncreaseSelection:(TextGranularity)granularity
1418 {
1419     [self accessibilityModifySelection:granularity increase:YES];
1420 }
1421
1422 - (void)accessibilityDecreaseSelection:(TextGranularity)granularity
1423 {
1424     [self accessibilityModifySelection:granularity increase:NO];
1425 }
1426
1427 - (void)accessibilityMoveSelectionToMarker:(WebAccessibilityTextMarker *)marker
1428 {
1429     if (![self _prepareAccessibilityCall])
1430         return;
1431     
1432     VisiblePosition visiblePosition = [marker visiblePosition];
1433     if (visiblePosition.isNull())
1434         return;
1435
1436     FrameSelection& frameSelection = m_object->document()->frame()->selection();
1437     frameSelection.moveTo(visiblePosition, UserTriggered);
1438 }
1439
1440 - (void)accessibilityIncrement
1441 {
1442     if (![self _prepareAccessibilityCall])
1443         return;
1444
1445     m_object->increment();
1446 }
1447
1448 - (void)accessibilityDecrement
1449 {
1450     if (![self _prepareAccessibilityCall])
1451         return;
1452
1453     m_object->decrement();
1454 }
1455
1456 #pragma mark Accessibility Text Marker Handlers
1457
1458 - (BOOL)_addAccessibilityObject:(AccessibilityObject*)axObject toTextMarkerArray:(NSMutableArray *)array
1459 {
1460     if (!axObject)
1461         return NO;
1462     
1463     AccessibilityObjectWrapper* wrapper = axObject->wrapper();
1464     if (!wrapper)
1465         return NO;
1466
1467     // Don't add the same object twice, but since this has already been added, we should return
1468     // YES because we want to inform that it's in the array
1469     if ([array containsObject:wrapper])
1470         return YES;
1471     
1472     // Explicity set that this is now an element (in case other logic tries to override).
1473     [wrapper setValue:[NSNumber numberWithBool:YES] forKey:@"isAccessibilityElement"];    
1474     [array addObject:wrapper];
1475     return YES;
1476 }
1477
1478 - (NSString *)stringForTextMarkers:(NSArray *)markers
1479 {
1480     if (![self _prepareAccessibilityCall])
1481         return nil;
1482     
1483     if ([markers count] != 2)
1484         return nil;
1485     
1486     WebAccessibilityTextMarker* startMarker = [markers objectAtIndex:0];
1487     WebAccessibilityTextMarker* endMarker = [markers objectAtIndex:1];
1488     if (![startMarker isKindOfClass:[WebAccessibilityTextMarker class]] || ![endMarker isKindOfClass:[WebAccessibilityTextMarker class]])
1489         return nil;
1490     
1491     // extract the start and end VisiblePosition
1492     VisiblePosition startVisiblePosition = [startMarker visiblePosition];
1493     if (startVisiblePosition.isNull())
1494         return nil;
1495     
1496     VisiblePosition endVisiblePosition = [endMarker visiblePosition];
1497     if (endVisiblePosition.isNull())
1498         return nil;
1499
1500     VisiblePositionRange visiblePosRange = VisiblePositionRange(startVisiblePosition, endVisiblePosition);
1501     return m_object->stringForVisiblePositionRange(visiblePosRange);
1502 }
1503
1504 static int blockquoteLevel(RenderObject* renderer)
1505 {
1506     if (!renderer)
1507         return 0;
1508     
1509     int result = 0;
1510     for (Node* node = renderer->node(); node; node = node->parentNode()) {
1511         if (node->hasTagName(blockquoteTag))
1512             result += 1;
1513     }
1514     
1515     return result;
1516 }
1517
1518 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
1519 {
1520     int quoteLevel = blockquoteLevel(renderer);
1521     
1522     if (quoteLevel)
1523         [attrString addAttribute:UIAccessibilityTokenBlockquoteLevel value:[NSNumber numberWithInt:quoteLevel] range:range];
1524     else
1525         [attrString removeAttribute:UIAccessibilityTokenBlockquoteLevel range:range];
1526 }
1527
1528 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
1529 {
1530     if (!renderer)
1531         return;
1532     
1533     AccessibilityObject* parentObject = renderer->document().axObjectCache()->getOrCreate(renderer->parent());
1534     int parentHeadingLevel = parentObject->headingLevel();
1535     
1536     if (parentHeadingLevel)
1537         [attrString addAttribute:UIAccessibilityTokenHeadingLevel value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
1538     else
1539         [attrString removeAttribute:UIAccessibilityTokenHeadingLevel range:range];
1540 }
1541
1542 static void AXAttributeStringSetFont(NSMutableAttributedString* attrString, CTFontRef font, NSRange range)
1543 {
1544     if (!font)
1545         return;
1546     
1547     RetainPtr<CFStringRef> fullName = adoptCF(CTFontCopyFullName(font));
1548     RetainPtr<CFStringRef> familyName = adoptCF(CTFontCopyFamilyName(font));
1549
1550     NSNumber* size = [NSNumber numberWithFloat:CTFontGetSize(font)];
1551     CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font);
1552     NSNumber* bold = [NSNumber numberWithBool:(traits & kCTFontTraitBold)];
1553     if (fullName)
1554         [attrString addAttribute:UIAccessibilityTokenFontName value:(NSString*)fullName.get() range:range];
1555     if (familyName)
1556         [attrString addAttribute:UIAccessibilityTokenFontFamily value:(NSString*)familyName.get() range:range];
1557     if ([size boolValue])
1558         [attrString addAttribute:UIAccessibilityTokenFontSize value:size range:range];
1559     if ([bold boolValue] || (traits & kCTFontTraitBold))
1560         [attrString addAttribute:UIAccessibilityTokenBold value:[NSNumber numberWithBool:YES] range:range];
1561     if (traits & kCTFontTraitItalic)
1562         [attrString addAttribute:UIAccessibilityTokenItalic value:[NSNumber numberWithBool:YES] range:range];
1563
1564 }
1565
1566 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
1567 {
1568     if (number)
1569         [attrString addAttribute:attribute value:number range:range];
1570     else
1571         [attrString removeAttribute:attribute range:range];
1572 }
1573
1574 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
1575 {
1576     RenderStyle& style = renderer->style();
1577     
1578     // set basic font info
1579     AXAttributeStringSetFont(attrString, style.font().primaryFont()->getCTFont(), range);
1580                 
1581     int decor = style.textDecorationsInEffect();
1582     if ((decor & (TextDecorationUnderline | TextDecorationLineThrough)) != 0) {
1583         // find colors using quirk mode approach (strict mode would use current
1584         // color for all but the root line box, which would use getTextDecorationColors)
1585         Color underline, overline, linethrough;
1586         renderer->getTextDecorationColors(decor, underline, overline, linethrough);
1587         
1588         if (decor & TextDecorationUnderline)
1589             AXAttributeStringSetNumber(attrString, UIAccessibilityTokenUnderline, [NSNumber numberWithBool:YES], range);
1590     }
1591 }
1592
1593 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, NSString *text)
1594 {
1595     // skip invisible text
1596     if (!node->renderer())
1597         return;
1598     
1599     // easier to calculate the range before appending the string
1600     NSRange attrStringRange = NSMakeRange([attrString length], [text length]);
1601     
1602     // append the string from this node
1603     [[attrString mutableString] appendString:text];
1604     
1605     // set new attributes
1606     AXAttributeStringSetStyle(attrString, node->renderer(), attrStringRange);
1607     AXAttributeStringSetHeadingLevel(attrString, node->renderer(), attrStringRange);
1608     AXAttributeStringSetBlockquoteLevel(attrString, node->renderer(), attrStringRange);    
1609 }
1610
1611
1612 // This method is intended to return an array of strings and accessibility elements that 
1613 // represent the objects on one line of rendered web content. The array of markers sent
1614 // in should be ordered and contain only a start and end marker.
1615 - (NSArray *)arrayOfTextForTextMarkers:(NSArray *)markers attributed:(BOOL)attributed
1616 {
1617     if (![self _prepareAccessibilityCall])
1618         return nil;
1619
1620     if ([markers count] != 2)
1621         return nil;
1622     
1623     WebAccessibilityTextMarker* startMarker = [markers objectAtIndex:0];
1624     WebAccessibilityTextMarker* endMarker = [markers objectAtIndex:1];
1625     if (![startMarker isKindOfClass:[WebAccessibilityTextMarker class]] || ![endMarker isKindOfClass:[WebAccessibilityTextMarker class]])
1626         return nil;
1627     
1628     // extract the start and end VisiblePosition
1629     VisiblePosition startVisiblePosition = [startMarker visiblePosition];
1630     if (startVisiblePosition.isNull())
1631         return nil;
1632     
1633     VisiblePosition endVisiblePosition = [endMarker visiblePosition];
1634     if (endVisiblePosition.isNull())
1635         return nil;
1636     
1637     // iterate over the range to build the AX attributed string
1638     NSMutableArray* array = [[NSMutableArray alloc] init];
1639     TextIterator it(makeRange(startVisiblePosition, endVisiblePosition).get());
1640     for (; !it.atEnd(); it.advance()) {
1641         // locate the node and starting offset for this range
1642         int exception = 0;
1643         Node* node = it.range()->startContainer(exception);
1644         ASSERT(node == it.range()->endContainer(exception));
1645         int offset = it.range()->startOffset(exception);
1646         
1647         // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
1648         if (it.text().length() != 0) {
1649             if (!attributed) {
1650                 // First check if this is represented by a link.
1651                 AccessibilityObject* linkObject = AccessibilityObject::anchorElementForNode(node);
1652                 if ([self _addAccessibilityObject:linkObject toTextMarkerArray:array])
1653                     continue;
1654                 
1655                 // Next check if this region is represented by a heading.
1656                 AccessibilityObject* headingObject = AccessibilityObject::headingElementForNode(node);
1657                 if ([self _addAccessibilityObject:headingObject toTextMarkerArray:array])
1658                     continue;
1659                 
1660                 String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition())); 
1661                 
1662                 if (!listMarkerText.isEmpty()) 
1663                     [array addObject:listMarkerText];
1664                 // There was not an element representation, so just return the text.
1665                 [array addObject:it.text().createNSString().get()];
1666             }
1667             else
1668             {
1669                 String listMarkerText = m_object->listMarkerTextForNodeAndPosition(node, VisiblePosition(it.range()->startPosition())); 
1670
1671                 if (!listMarkerText.isEmpty()) {
1672                     NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
1673                     AXAttributedStringAppendText(attrString, node, listMarkerText);
1674                     [array addObject:attrString];
1675                     [attrString release];
1676                 }
1677                 
1678                 NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] init];
1679                 AXAttributedStringAppendText(attrString, node, it.text().createNSStringWithoutCopying().get());
1680                 [array addObject:attrString];
1681                 [attrString release];
1682             }
1683         } else {
1684             Node* replacedNode = node->childNode(offset);
1685             if (replacedNode) {
1686                 AccessibilityObject* obj = m_object->axObjectCache()->getOrCreate(replacedNode->renderer());
1687                 if (obj && !obj->accessibilityIsIgnored())
1688                     [self _addAccessibilityObject:obj toTextMarkerArray:array];
1689             }
1690         }
1691     }
1692     
1693     return [array autorelease];
1694 }
1695
1696 - (NSRange)_convertToNSRange:(Range *)range
1697 {
1698     if (!range || !range->startContainer())
1699         return NSMakeRange(NSNotFound, 0);
1700     
1701     Document* document = m_object->document();
1702     Element* selectionRoot = document->frame()->selection().selection().rootEditableElement();
1703     Element* scope = selectionRoot ? selectionRoot : document->documentElement();
1704     
1705     // Mouse events may cause TSM to attempt to create an NSRange for a portion of the view
1706     // that is not inside the current editable region.  These checks ensure we don't produce
1707     // potentially invalid data when responding to such requests.
1708     if (range->startContainer() != scope && !range->startContainer()->isDescendantOf(scope))
1709         return NSMakeRange(NSNotFound, 0);
1710     if (range->endContainer() != scope && !range->endContainer()->isDescendantOf(scope))
1711         return NSMakeRange(NSNotFound, 0);
1712     
1713     RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
1714     ASSERT(testRange->startContainer() == scope);
1715     int startPosition = TextIterator::rangeLength(testRange.get());
1716     
1717     ExceptionCode ec;
1718     testRange->setEnd(range->endContainer(), range->endOffset(), ec);
1719     ASSERT(testRange->startContainer() == scope);
1720     int endPosition = TextIterator::rangeLength(testRange.get());
1721     return NSMakeRange(startPosition, endPosition - startPosition);
1722 }
1723
1724 - (PassRefPtr<Range>)_convertToDOMRange:(NSRange)nsrange
1725 {
1726     if (nsrange.location > INT_MAX)
1727         return 0;
1728     if (nsrange.length > INT_MAX || nsrange.location + nsrange.length > INT_MAX)
1729         nsrange.length = INT_MAX - nsrange.location;
1730         
1731     // our critical assumption is that we are only called by input methods that
1732     // concentrate on a given area containing the selection
1733     // We have to do this because of text fields and textareas. The DOM for those is not
1734     // directly in the document DOM, so serialization is problematic. Our solution is
1735     // to use the root editable element of the selection start as the positional base.
1736     // That fits with AppKit's idea of an input context.
1737     Document* document = m_object->document();
1738     Element* selectionRoot = document->frame()->selection().selection().rootEditableElement();
1739     Element* scope = selectionRoot ? selectionRoot : document->documentElement();
1740     return TextIterator::rangeFromLocationAndLength(scope, nsrange.location, nsrange.length);
1741 }
1742
1743 // This method is intended to take a text marker representing a VisiblePosition and convert it
1744 // into a normalized location within the document.
1745 - (NSInteger)positionForTextMarker:(WebAccessibilityTextMarker *)marker
1746 {
1747     if (![self _prepareAccessibilityCall])
1748         return NSNotFound;
1749
1750     if (!marker)
1751         return NSNotFound;    
1752
1753     VisibleSelection selection([marker visiblePosition]);
1754     RefPtr<Range> range = selection.toNormalizedRange();
1755     NSRange nsRange = [self _convertToNSRange:range.get()];
1756     return nsRange.location;
1757 }
1758
1759 - (NSArray *)textMarkerRange
1760 {
1761     if (![self _prepareAccessibilityCall])
1762         return nil;
1763     
1764     VisiblePositionRange range = m_object->visiblePositionRange();
1765     VisiblePosition startPosition = range.start;
1766     VisiblePosition endPosition = range.end;
1767     WebAccessibilityTextMarker* start = [WebAccessibilityTextMarker textMarkerWithVisiblePosition:startPosition cache:m_object->axObjectCache()];
1768     WebAccessibilityTextMarker* end = [WebAccessibilityTextMarker textMarkerWithVisiblePosition:endPosition cache:m_object->axObjectCache()];
1769     
1770     return [NSArray arrayWithObjects:start, end, nil];
1771 }
1772
1773 // A method to get the normalized text cursor range of an element. Used in DumpRenderTree.
1774 - (NSRange)elementTextRange
1775 {
1776     if (![self _prepareAccessibilityCall])
1777         return NSMakeRange(NSNotFound, 0);
1778
1779     NSArray *markers = [self textMarkerRange];
1780     if ([markers count] != 2)
1781         return NSMakeRange(NSNotFound, 0);
1782     
1783     WebAccessibilityTextMarker *startMarker = [markers objectAtIndex:0];
1784     WebAccessibilityTextMarker *endMarker = [markers objectAtIndex:1];
1785     
1786     NSInteger startPosition = [self positionForTextMarker:startMarker];
1787     NSInteger endPosition = [self positionForTextMarker:endMarker];
1788     
1789     return NSMakeRange(startPosition, endPosition - startPosition);
1790 }
1791
1792 - (AccessibilityObjectWrapper *)accessibilityObjectForTextMarker:(WebAccessibilityTextMarker *)marker
1793 {
1794     if (![self _prepareAccessibilityCall])
1795         return nil;
1796
1797     if (!marker)
1798         return nil;
1799     
1800     VisiblePosition visiblePosition = [marker visiblePosition];
1801     AccessibilityObject* obj = m_object->accessibilityObjectForPosition(visiblePosition);
1802     if (!obj)
1803         return nil;
1804     
1805     return AccessibilityUnignoredAncestor(obj->wrapper());
1806 }
1807
1808 - (NSArray *)textMarkerRangeForSelection
1809 {
1810     if (![self _prepareAccessibilityCall])
1811         return nil;
1812     
1813     VisibleSelection selection = m_object->selection();
1814     if (selection.isNone())
1815         return nil;
1816     VisiblePosition startPosition = selection.visibleStart();
1817     VisiblePosition endPosition = selection.visibleEnd();
1818
1819     WebAccessibilityTextMarker* startMarker = [WebAccessibilityTextMarker textMarkerWithVisiblePosition:startPosition cache:m_object->axObjectCache()];
1820     WebAccessibilityTextMarker* endMarker = [WebAccessibilityTextMarker textMarkerWithVisiblePosition:endPosition cache:m_object->axObjectCache()];
1821     if (!startMarker || !endMarker)
1822         return nil;
1823     
1824     return [NSArray arrayWithObjects:startMarker, endMarker, nil];
1825 }
1826
1827 - (WebAccessibilityTextMarker *)textMarkerForPosition:(NSInteger)position
1828 {
1829     if (![self _prepareAccessibilityCall])
1830         return nil;
1831
1832     PassRefPtr<Range> range = [self _convertToDOMRange:NSMakeRange(position, 0)];
1833     if (!range)
1834         return nil;
1835     
1836     VisibleSelection selection = VisibleSelection(range.get(), DOWNSTREAM);
1837
1838     VisiblePosition visiblePosition = selection.visibleStart();
1839     return [WebAccessibilityTextMarker textMarkerWithVisiblePosition:visiblePosition cache:m_object->axObjectCache()];
1840 }
1841
1842 - (id)_stringForRange:(NSRange)range attributed:(BOOL)attributed
1843 {
1844     if (![self _prepareAccessibilityCall])
1845         return nil;
1846     
1847     WebAccessibilityTextMarker* startMarker = [self textMarkerForPosition:range.location];
1848     WebAccessibilityTextMarker* endMarker = [self textMarkerForPosition:NSMaxRange(range)];
1849     
1850     // Clients don't always know the exact range, rather than force them to compute it,
1851     // allow clients to overshoot and use the max text marker range.
1852     if (!startMarker || !endMarker) {
1853         NSArray *markers = [self textMarkerRange];
1854         if ([markers count] != 2)
1855             return nil;
1856         if (!startMarker)
1857             startMarker = [markers objectAtIndex:0];
1858         if (!endMarker)
1859             endMarker = [markers objectAtIndex:1];
1860     }
1861     
1862     NSArray* array = [self arrayOfTextForTextMarkers:[NSArray arrayWithObjects:startMarker, endMarker, nil] attributed:attributed];
1863     Class returnClass = attributed ? [NSMutableAttributedString class] : [NSMutableString class];
1864     id returnValue = [[[returnClass alloc] init] autorelease];
1865     
1866     NSInteger count = [array count];
1867     for (NSInteger k = 0; k < count; ++k) {
1868         id object = [array objectAtIndex:k];
1869
1870         if (![object isKindOfClass:returnClass])
1871             continue;
1872         
1873         if (attributed)
1874             [(NSMutableAttributedString *)returnValue appendAttributedString:object];
1875         else
1876             [(NSMutableString *)returnValue appendString:object];
1877     }
1878     return returnValue;
1879 }
1880
1881
1882 // A convenience method for getting the text of a NSRange. Currently used only by DRT.
1883 - (NSString *)stringForRange:(NSRange)range
1884 {
1885     return [self _stringForRange:range attributed:NO];
1886 }
1887
1888 - (NSAttributedString *)attributedStringForRange:(NSRange)range
1889 {
1890     return [self _stringForRange:range attributed:YES];
1891 }
1892
1893 // A convenience method for getting the accessibility objects of a NSRange. Currently used only by DRT.
1894 - (NSArray *)elementsForRange:(NSRange)range
1895 {
1896     if (![self _prepareAccessibilityCall])
1897         return nil;
1898     
1899     WebAccessibilityTextMarker* startMarker = [self textMarkerForPosition:range.location];
1900     WebAccessibilityTextMarker* endMarker = [self textMarkerForPosition:NSMaxRange(range)];
1901     if (!startMarker || !endMarker)
1902         return nil;
1903     
1904     NSArray* array = [self arrayOfTextForTextMarkers:[NSArray arrayWithObjects:startMarker, endMarker, nil] attributed:NO];
1905     NSMutableArray* elements = [NSMutableArray array];
1906     for (id element in array) {
1907         if (![element isKindOfClass:[AccessibilityObjectWrapper class]])
1908             continue;
1909         [elements addObject:element];
1910     }
1911     return elements;
1912 }
1913
1914 - (NSString *)selectionRangeString
1915 {
1916     NSArray *markers = [self textMarkerRangeForSelection];
1917     return [self stringForTextMarkers:markers];
1918 }
1919
1920 - (WebAccessibilityTextMarker *)selectedTextMarker
1921 {
1922     if (![self _prepareAccessibilityCall])
1923         return nil;
1924     
1925     VisibleSelection selection = m_object->selection();
1926     VisiblePosition position = selection.visibleStart();
1927     
1928     // if there's no selection, start at the top of the document
1929     if (position.isNull())
1930         position = startOfDocument(m_object->document());
1931     
1932     return [WebAccessibilityTextMarker textMarkerWithVisiblePosition:position cache:m_object->axObjectCache()];
1933 }
1934
1935 // This method is intended to return the marker at the end of the line starting at
1936 // the marker that is passed into the method.
1937 - (WebAccessibilityTextMarker *)lineEndMarkerForMarker:(WebAccessibilityTextMarker *)marker
1938 {
1939     if (![self _prepareAccessibilityCall])
1940         return nil;
1941
1942     if (!marker)
1943         return nil;
1944     
1945     VisiblePosition start = [marker visiblePosition];
1946     VisiblePosition lineEnd = m_object->nextLineEndPosition(start);
1947     
1948     return [WebAccessibilityTextMarker textMarkerWithVisiblePosition:lineEnd cache:m_object->axObjectCache()];
1949 }
1950
1951 // This method is intended to return the marker at the start of the line starting at
1952 // the marker that is passed into the method.
1953 - (WebAccessibilityTextMarker *)lineStartMarkerForMarker:(WebAccessibilityTextMarker *)marker
1954 {
1955     if (![self _prepareAccessibilityCall])
1956         return nil;
1957
1958     if (!marker)
1959         return nil;
1960     
1961     VisiblePosition start = [marker visiblePosition];
1962     VisiblePosition lineStart = m_object->previousLineStartPosition(start);
1963     
1964     return [WebAccessibilityTextMarker textMarkerWithVisiblePosition:lineStart cache:m_object->axObjectCache()];
1965 }
1966
1967 - (WebAccessibilityTextMarker *)nextMarkerForMarker:(WebAccessibilityTextMarker *)marker
1968 {
1969     if (![self _prepareAccessibilityCall])
1970         return nil;
1971
1972     if (!marker)
1973         return nil;
1974     
1975     VisiblePosition start = [marker visiblePosition];
1976     VisiblePosition nextMarker = m_object->nextVisiblePosition(start);
1977     
1978     return [WebAccessibilityTextMarker textMarkerWithVisiblePosition:nextMarker cache:m_object->axObjectCache()];
1979 }
1980
1981 // This method is intended to return the marker at the start of the line starting at
1982 // the marker that is passed into the method.
1983 - (WebAccessibilityTextMarker *)previousMarkerForMarker:(WebAccessibilityTextMarker *)marker
1984 {
1985     if (![self _prepareAccessibilityCall])
1986         return nil;
1987
1988     if (!marker)
1989         return nil;
1990     
1991     VisiblePosition start = [marker visiblePosition];
1992     VisiblePosition previousMarker = m_object->previousVisiblePosition(start);
1993     
1994     return [WebAccessibilityTextMarker textMarkerWithVisiblePosition:previousMarker cache:m_object->axObjectCache()];
1995 }
1996
1997 // This method is intended to return the bounds of a text marker range in screen coordinates.
1998 - (CGRect)frameForTextMarkers:(NSArray *)array
1999 {
2000     if (![self _prepareAccessibilityCall])
2001         return CGRectZero;
2002
2003     if ([array count] != 2)
2004         return CGRectZero;
2005     
2006     WebAccessibilityTextMarker* startMarker = [array objectAtIndex:0];
2007     WebAccessibilityTextMarker* endMarker = [array objectAtIndex:1];
2008     if (![startMarker isKindOfClass:[WebAccessibilityTextMarker class]] || ![endMarker isKindOfClass:[WebAccessibilityTextMarker class]])
2009         return CGRectZero;
2010
2011     IntRect rect = m_object->boundsForVisiblePositionRange(VisiblePositionRange([startMarker visiblePosition], [endMarker visiblePosition]));
2012     return [self convertRectToScreenSpace:rect];
2013 }
2014
2015 - (WebAccessibilityTextMarker *)textMarkerForPoint:(CGPoint)point
2016 {
2017     if (![self _prepareAccessibilityCall])
2018         return nil;
2019     
2020     VisiblePosition pos = m_object->visiblePositionForPoint(IntPoint(point));
2021     return [WebAccessibilityTextMarker textMarkerWithVisiblePosition:pos cache:m_object->axObjectCache()];
2022 }
2023
2024 - (NSString *)accessibilityIdentifier
2025 {
2026     if (![self _prepareAccessibilityCall])
2027         return nil;
2028     
2029     return m_object->getAttribute(HTMLNames::idAttr);
2030 }
2031
2032 - (NSString *)accessibilitySpeechHint
2033 {
2034     if (![self _prepareAccessibilityCall])
2035         return nil;
2036
2037     switch (m_object->speakProperty()) {
2038     default:
2039     case SpeakNormal:
2040         return @"normal";
2041     case SpeakNone:
2042         return @"none";
2043     case SpeakSpellOut:
2044         return @"spell-out";
2045     case SpeakDigits:
2046         return @"digits";
2047     case SpeakLiteralPunctuation:
2048         return @"literal-punctuation";
2049     case SpeakNoPunctuation:
2050         return @"no-punctuation";
2051     }
2052     
2053     return nil;
2054 }
2055
2056 - (BOOL)accessibilityARIAIsBusy
2057 {
2058     if (![self _prepareAccessibilityCall])
2059         return nil;
2060
2061     return m_object->ariaLiveRegionBusy();
2062 }
2063
2064 - (NSString *)accessibilityARIALiveRegionStatus
2065 {
2066     if (![self _prepareAccessibilityCall])
2067         return nil;
2068
2069     return m_object->ariaLiveRegionStatus();
2070 }
2071
2072 - (NSString *)accessibilityARIARelevantStatus
2073 {
2074     if (![self _prepareAccessibilityCall])
2075         return nil;
2076     
2077     return m_object->ariaLiveRegionRelevant();
2078 }
2079
2080 - (BOOL)accessibilityARIALiveRegionIsAtomic
2081 {
2082     if (![self _prepareAccessibilityCall])
2083         return nil;
2084     
2085     return m_object->ariaLiveRegionAtomic();
2086 }
2087
2088 - (BOOL)accessibilityIsExpanded
2089 {
2090     if (![self _prepareAccessibilityCall])
2091         return NO;
2092
2093     return m_object->isExpanded();
2094 }
2095
2096 - (NSString *)accessibilityInvalidStatus
2097 {
2098     if (![self _prepareAccessibilityCall])
2099         return nil;
2100     
2101     return m_object->invalidStatus();
2102 }
2103
2104 - (WebAccessibilityObjectWrapper *)accessibilityMathRootIndexObject
2105 {
2106     if (![self _prepareAccessibilityCall])
2107         return nil;
2108
2109     return m_object->mathRootIndexObject() ? m_object->mathRootIndexObject()->wrapper() : 0;
2110 }
2111
2112 - (WebAccessibilityObjectWrapper *)accessibilityMathRadicandObject
2113 {
2114     if (![self _prepareAccessibilityCall])
2115         return nil;
2116
2117     return m_object->mathRadicandObject() ? m_object->mathRadicandObject()->wrapper() : 0;
2118 }
2119
2120 - (WebAccessibilityObjectWrapper *)accessibilityMathNumeratorObject
2121 {
2122     if (![self _prepareAccessibilityCall])
2123         return nil;
2124
2125     return m_object->mathNumeratorObject() ? m_object->mathNumeratorObject()->wrapper() : 0;
2126 }
2127
2128 - (WebAccessibilityObjectWrapper *)accessibilityMathDenominatorObject
2129 {
2130     if (![self _prepareAccessibilityCall])
2131         return nil;
2132
2133     return m_object->mathDenominatorObject() ? m_object->mathDenominatorObject()->wrapper() : 0;
2134 }
2135
2136 - (WebAccessibilityObjectWrapper *)accessibilityMathBaseObject
2137 {
2138     if (![self _prepareAccessibilityCall])
2139         return nil;
2140
2141     return m_object->mathBaseObject() ? m_object->mathBaseObject()->wrapper() : 0;
2142 }
2143
2144 - (WebAccessibilityObjectWrapper *)accessibilityMathSubscriptObject
2145 {
2146     if (![self _prepareAccessibilityCall])
2147         return nil;
2148
2149     return m_object->mathSubscriptObject() ? m_object->mathSubscriptObject()->wrapper() : 0;
2150 }
2151
2152 - (WebAccessibilityObjectWrapper *)accessibilityMathSuperscriptObject
2153 {
2154     if (![self _prepareAccessibilityCall])
2155         return nil;
2156
2157     return m_object->mathSuperscriptObject() ? m_object->mathSuperscriptObject()->wrapper() : 0;
2158 }
2159
2160 - (WebAccessibilityObjectWrapper *)accessibilityMathUnderObject
2161 {
2162     if (![self _prepareAccessibilityCall])
2163         return nil;
2164
2165     return m_object->mathUnderObject() ? m_object->mathUnderObject()->wrapper() : 0;
2166 }
2167
2168 - (WebAccessibilityObjectWrapper *)accessibilityMathOverObject
2169 {
2170     if (![self _prepareAccessibilityCall])
2171         return nil;
2172
2173     return m_object->mathOverObject() ? m_object->mathOverObject()->wrapper() : 0;
2174 }
2175
2176 - (NSString *)accessibilityPlatformMathSubscriptKey
2177 {
2178     return @"AXMSubscriptObject";
2179 }
2180
2181 - (NSString *)accessibilityPlatformMathSuperscriptKey
2182 {
2183     return @"AXMSuperscriptObject";
2184 }
2185
2186 - (NSArray *)accessibilityMathPostscripts
2187 {
2188     if (![self _prepareAccessibilityCall])
2189         return nil;
2190     
2191     return [self accessibilityMathPostscriptPairs];
2192 }
2193
2194 - (NSArray *)accessibilityMathPrescripts
2195 {
2196     if (![self _prepareAccessibilityCall])
2197         return nil;
2198     
2199     return [self accessibilityMathPrescriptPairs];
2200 }
2201
2202 - (NSString *)accessibilityMathFencedOpenString
2203 {
2204     if (![self _prepareAccessibilityCall])
2205         return nil;
2206
2207     return m_object->mathFencedOpenString();
2208 }
2209
2210 - (NSString *)accessibilityMathFencedCloseString
2211 {
2212     if (![self _prepareAccessibilityCall])
2213         return nil;
2214
2215     return m_object->mathFencedCloseString();
2216 }
2217
2218 - (BOOL)accessibilityIsMathTopObject
2219 {
2220     if (![self _prepareAccessibilityCall])
2221         return NO;
2222
2223     return m_object->roleValue() == DocumentMathRole;
2224 }
2225
2226 - (NSInteger)accessibilityMathLineThickness
2227 {
2228     if (![self _prepareAccessibilityCall])
2229         return 0;
2230
2231     return m_object->mathLineThickness();
2232 }
2233
2234 - (NSString *)accessibilityMathType
2235 {
2236     if (![self _prepareAccessibilityCall])
2237         return nil;
2238
2239     if (m_object->roleValue() == MathElementRole) {
2240         if (m_object->isMathFraction())
2241             return @"AXMathFraction";
2242         if (m_object->isMathFenced())
2243             return @"AXMathFenced";
2244         if (m_object->isMathSubscriptSuperscript())
2245             return @"AXMathSubscriptSuperscript";
2246         if (m_object->isMathRow())
2247             return @"AXMathRow";
2248         if (m_object->isMathUnderOver())
2249             return @"AXMathUnderOver";
2250         if (m_object->isMathSquareRoot())
2251             return @"AXMathSquareRoot";
2252         if (m_object->isMathRoot())
2253             return @"AXMathRoot";
2254         if (m_object->isMathText())
2255             return @"AXMathText";
2256         if (m_object->isMathNumber())
2257             return @"AXMathNumber";
2258         if (m_object->isMathIdentifier())
2259             return @"AXMathIdentifier";
2260         if (m_object->isMathTable())
2261             return @"AXMathTable";
2262         if (m_object->isMathTableRow())
2263             return @"AXMathTableRow";
2264         if (m_object->isMathTableCell())
2265             return @"AXMathTableCell";
2266         if (m_object->isMathFenceOperator())
2267             return @"AXMathFenceOperator";
2268         if (m_object->isMathSeparatorOperator())
2269             return @"AXMathSeparatorOperator";
2270         if (m_object->isMathOperator())
2271             return @"AXMathOperator";
2272         if (m_object->isMathMultiscript())
2273             return @"AXMathMultiscript";
2274     }
2275     
2276     return nil;
2277 }
2278
2279 - (CGPoint)accessibilityClickPoint
2280 {
2281     return m_object->clickPoint();
2282 }
2283
2284 // These are used by DRT so that it can know when notifications are sent.
2285 // Since they are static, only one callback can be installed at a time (that's all DRT should need).
2286 typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
2287 static AXPostedNotificationCallback AXNotificationCallback = 0;
2288 static void* AXPostedNotificationContext = 0;
2289
2290 - (void)accessibilitySetPostedNotificationCallback:(AXPostedNotificationCallback)function withContext:(void*)context
2291 {
2292     AXNotificationCallback = function;
2293     AXPostedNotificationContext = context;
2294 }
2295
2296 - (void)accessibilityPostedNotification:(NSString *)notificationName
2297 {
2298     if (AXNotificationCallback && notificationName)
2299         AXNotificationCallback(self, notificationName, AXPostedNotificationContext);
2300 }
2301
2302 #ifndef NDEBUG
2303 - (NSString *)description
2304 {
2305     CGRect frame = [self accessibilityFrame];
2306     return [NSString stringWithFormat:@"Role: (%d) - Text: %@: Value: %@ -- Frame: %f %f %f %f", m_object ? m_object->roleValue() : 0, [self accessibilityLabel], [self accessibilityValue], frame.origin.x, frame.origin.y, frame.size.width, frame.size.height];
2307 }
2308 #endif
2309
2310 @end
2311
2312 #endif // HAVE(ACCESSIBILITY) && PLATFORM(IOS)