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 "DumpRenderTree.h"
28#import "AccessibilityUIElement.h"
29
30#import <Foundation/Foundation.h>
31#import <JavaScriptCore/JSRetainPtr.h>
32#import <JavaScriptCore/JSStringRef.h>
33#import <JavaScriptCore/JSStringRefCF.h>
34#import <WebKit/WebFrame.h>
35#import <WebKit/WebHTMLView.h>
36#import <WebKit/WebTypesInternal.h>
37#import <wtf/RetainPtr.h>
38#import <wtf/Vector.h>
39
40#ifdef BUILDING_ON_TIGER
41#define NSAccessibilityValueDescriptionAttribute @"AXValueDescription"
42#endif
43
44#ifndef NSAccessibilityOwnsAttribute
45#define NSAccessibilityOwnsAttribute @"AXOwns"
46#endif
47
48#ifndef NSAccessibilityGrabbedAttribute
49#define NSAccessibilityGrabbedAttribute @"AXGrabbed"
50#endif
51
52#ifndef NSAccessibilityDropEffectsAttribute
53#define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
54#endif
55
56// If an unsupported attribute is passed in, it will raise an accessibility exception. These are usually caught by the Accessibility Runtime to inform
57// the AX client app of the error. However, DRT is the AX client app, so it must catch these exceptions.
58#define BEGIN_AX_OBJC_EXCEPTIONS @try {
59#define END_AX_OBJC_EXCEPTIONS } @catch(NSException *e) { if (![[e name] isEqualToString:NSAccessibilityException]) @throw; }
60
61
62typedef void (*AXPostedNotificationCallback)(id element, NSString* notification, void* context);
63
64@interface NSObject (WebKitAccessibilityAdditions)
65- (NSArray *)accessibilityArrayAttributeValues:(NSString *)attribute index:(NSUInteger)index maxCount:(NSUInteger)maxCount;
66- (void)accessibilitySetShouldRepostNotifications:(BOOL)repost;
67- (NSUInteger)accessibilityIndexOfChild:(id)child;
68- (NSUInteger)accessibilityArrayAttributeCount:(NSString *)attribute;
69@end
70
71@interface NSString (JSStringRefAdditions)
72+ (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef;
73- (JSStringRef)createJSStringRef;
74@end
75
76@implementation NSString (JSStringRefAdditions)
77
78+ (NSString *)stringWithJSStringRef:(JSStringRef)jsStringRef
79{
80    if (!jsStringRef)
81        return NULL;
82
83    CFStringRef cfString = JSStringCopyCFString(kCFAllocatorDefault, jsStringRef);
84    return [(NSString *)cfString autorelease];
85}
86
87- (JSStringRef)createJSStringRef
88{
89    return JSStringCreateWithCFString((CFStringRef)self);
90}
91
92@end
93
94@interface AccessibilityNotificationHandler : NSObject
95{
96    id m_platformElement;
97    JSObjectRef m_notificationFunctionCallback;
98}
99
100@end
101
102@implementation AccessibilityNotificationHandler
103
104- (id)initWithPlatformElement:(id)platformElement
105{
106    self = [super init];
107
108    m_platformElement = platformElement;
109
110    // Once an object starts requesting notifications, it's on for the duration of the program.
111    // This is to avoid any race conditions between tests turning this flag on and off. Instead
112    // AccessibilityNotificationHandler can just listen when they want to.
113    [m_platformElement accessibilitySetShouldRepostNotifications:YES];
114    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_notificationReceived:) name:@"AXDRTNotification" object:nil];
115
116    return self;
117}
118
119- (void)dealloc
120{
121    [[NSNotificationCenter defaultCenter] removeObserver:self];
122    JSValueUnprotect([mainFrame globalContext], m_notificationFunctionCallback);
123    m_notificationFunctionCallback = 0;
124
125    [super dealloc];
126}
127
128- (void)_notificationReceived:(NSNotification *)notification
129{
130    NSString *notificationName = [[notification userInfo] objectForKey:@"notificationName"];
131    if (!notificationName)
132        return;
133
134    JSRetainPtr<JSStringRef> jsNotification(Adopt, [notificationName createJSStringRef]);
135    JSValueRef argument = JSValueMakeString([mainFrame globalContext], jsNotification.get());
136    JSObjectCallAsFunction([mainFrame globalContext], m_notificationFunctionCallback, 0, 1, &argument, 0);
137}
138
139- (void)setCallback:(JSObjectRef)callback
140{
141    if (!callback)
142        return;
143
144    // Release the old callback.
145    if (m_notificationFunctionCallback)
146        JSValueUnprotect([mainFrame globalContext], m_notificationFunctionCallback);
147
148    m_notificationFunctionCallback = callback;
149    JSValueProtect([mainFrame globalContext], m_notificationFunctionCallback);
150}
151
152@end
153
154AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
155    : m_element(element)
156    , m_notificationHandler(0)
157{
158    // FIXME: ap@webkit.org says ObjC objects need to be CFRetained/CFRelease to be GC-compliant on the mac.
159    [m_element retain];
160}
161
162AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
163    : m_element(other.m_element)
164    , m_notificationHandler(0)
165{
166    [m_element retain];
167}
168
169AccessibilityUIElement::~AccessibilityUIElement()
170{
171    // The notification handler should be nil because removeNotificationListener() should have been called in the test.
172    ASSERT(!m_notificationHandler);
173    [m_element release];
174}
175
176static NSString* descriptionOfValue(id valueObject, id focusedAccessibilityObject)
177{
178    if (!valueObject)
179        return NULL;
180
181    if ([valueObject isKindOfClass:[NSArray class]])
182        return [NSString stringWithFormat:@"<array of size %d>", [(NSArray*)valueObject count]];
183
184    if ([valueObject isKindOfClass:[NSNumber class]])
185        return [(NSNumber*)valueObject stringValue];
186
187    if ([valueObject isKindOfClass:[NSValue class]]) {
188        NSString* type = [NSString stringWithCString:[valueObject objCType] encoding:NSASCIIStringEncoding];
189        NSValue* value = (NSValue*)valueObject;
190        if ([type rangeOfString:@"NSRect"].length > 0)
191            return [NSString stringWithFormat:@"NSRect: %@", NSStringFromRect([value rectValue])];
192        if ([type rangeOfString:@"NSPoint"].length > 0)
193            return [NSString stringWithFormat:@"NSPoint: %@", NSStringFromPoint([value pointValue])];
194        if ([type rangeOfString:@"NSSize"].length > 0)
195            return [NSString stringWithFormat:@"NSSize: %@", NSStringFromSize([value sizeValue])];
196        if ([type rangeOfString:@"NSRange"].length > 0)
197            return [NSString stringWithFormat:@"NSRange: %@", NSStringFromRange([value rangeValue])];
198    }
199
200    // Strip absolute URL paths
201    NSString* description = [valueObject description];
202    NSRange range = [description rangeOfString:@"LayoutTests"];
203    if (range.length)
204        return [description substringFromIndex:range.location];
205
206    // Strip pointer locations
207    if ([description rangeOfString:@"0x"].length) {
208        NSString* role = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityRoleAttribute];
209        NSString* title = [focusedAccessibilityObject accessibilityAttributeValue:NSAccessibilityTitleAttribute];
210        if ([title length])
211            return [NSString stringWithFormat:@"<%@: '%@'>", role, title];
212        return [NSString stringWithFormat:@"<%@>", role];
213    }
214
215    return [valueObject description];
216}
217
218static NSString* attributesOfElement(id accessibilityObject)
219{
220    NSArray* supportedAttributes = [accessibilityObject accessibilityAttributeNames];
221
222    NSMutableString* attributesString = [NSMutableString string];
223    for (NSUInteger i = 0; i < [supportedAttributes count]; ++i) {
224        NSString* attribute = [supportedAttributes objectAtIndex:i];
225
226        // Right now, position provides useless and screen-specific information, so we do not
227        // want to include it for the sake of universally passing tests.
228        if ([attribute isEqualToString:@"AXPosition"])
229            continue;
230
231        // accessibilityAttributeValue: can throw an if an attribute is not returned.
232        // For DumpRenderTree's purpose, we should ignore those exceptions
233        BEGIN_AX_OBJC_EXCEPTIONS
234        id valueObject = [accessibilityObject accessibilityAttributeValue:attribute];
235        NSString* value = descriptionOfValue(valueObject, accessibilityObject);
236        [attributesString appendFormat:@"%@: %@\n", attribute, value];
237        END_AX_OBJC_EXCEPTIONS
238    }
239
240    return attributesString;
241}
242
243static JSStringRef concatenateAttributeAndValue(NSString* attribute, NSString* value)
244{
245    Vector<UniChar> buffer([attribute length]);
246    [attribute getCharacters:buffer.data()];
247    buffer.append(':');
248    buffer.append(' ');
249
250    Vector<UniChar> valueBuffer([value length]);
251    [value getCharacters:valueBuffer.data()];
252    buffer.append(valueBuffer);
253
254    return JSStringCreateWithCharacters(buffer.data(), buffer.size());
255}
256
257static void convertNSArrayToVector(NSArray* array, Vector<AccessibilityUIElement>& elementVector)
258{
259    NSUInteger count = [array count];
260    for (NSUInteger i = 0; i < count; ++i)
261        elementVector.append(AccessibilityUIElement([array objectAtIndex:i]));
262}
263
264static JSStringRef descriptionOfElements(Vector<AccessibilityUIElement>& elementVector)
265{
266    NSMutableString* allElementString = [NSMutableString string];
267    size_t size = elementVector.size();
268    for (size_t i = 0; i < size; ++i) {
269        NSString* attributes = attributesOfElement(elementVector[i].platformUIElement());
270        [allElementString appendFormat:@"%@\n------------\n", attributes];
271    }
272
273    return [allElementString createJSStringRef];
274}
275
276void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>& elementVector)
277{
278    BEGIN_AX_OBJC_EXCEPTIONS
279    NSArray* linkedElements = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
280    convertNSArrayToVector(linkedElements, elementVector);
281    END_AX_OBJC_EXCEPTIONS
282}
283
284void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>& elementVector)
285{
286    BEGIN_AX_OBJC_EXCEPTIONS
287    NSArray* linkElements = [m_element accessibilityAttributeValue:@"AXLinkUIElements"];
288    convertNSArrayToVector(linkElements, elementVector);
289    END_AX_OBJC_EXCEPTIONS
290}
291
292void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& elementVector)
293{
294    BEGIN_AX_OBJC_EXCEPTIONS
295    NSArray* children = [m_element accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
296    convertNSArrayToVector(children, elementVector);
297    END_AX_OBJC_EXCEPTIONS
298}
299
300void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
301{
302    BEGIN_AX_OBJC_EXCEPTIONS
303    NSArray* children = [m_element accessibilityArrayAttributeValues:NSAccessibilityChildrenAttribute index:location maxCount:length];
304    convertNSArrayToVector(children, elementVector);
305    END_AX_OBJC_EXCEPTIONS
306}
307
308int AccessibilityUIElement::childrenCount()
309{
310    Vector<AccessibilityUIElement> children;
311    getChildren(children);
312
313    return children.size();
314}
315
316AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
317{
318    id element = [m_element accessibilityHitTest:NSMakePoint(x, y)];
319    if (!element)
320        return nil;
321
322    return AccessibilityUIElement(element);
323}
324
325unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
326{
327    return [m_element accessibilityIndexOfChild:element->platformUIElement()];
328}
329
330AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
331{
332    Vector<AccessibilityUIElement> children;
333    getChildrenWithRange(children, index, 1);
334
335    if (children.size() == 1)
336        return children[0];
337    return 0;
338}
339
340AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
341{
342    BEGIN_AX_OBJC_EXCEPTIONS
343    NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
344    if (index < [objects count])
345        return [objects objectAtIndex:index];
346    END_AX_OBJC_EXCEPTIONS
347
348    return 0;
349}
350
351AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
352{
353    BEGIN_AX_OBJC_EXCEPTIONS
354    NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityOwnsAttribute];
355    if (index < [objects count])
356        return [objects objectAtIndex:index];
357    END_AX_OBJC_EXCEPTIONS
358
359    return 0;
360}
361
362AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
363{
364    BEGIN_AX_OBJC_EXCEPTIONS
365    NSArray* objects = [m_element accessibilityAttributeValue:NSAccessibilityLinkedUIElementsAttribute];
366    if (index < [objects count])
367        return [objects objectAtIndex:index];
368    END_AX_OBJC_EXCEPTIONS
369
370    return 0;
371}
372
373AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
374{
375    BEGIN_AX_OBJC_EXCEPTIONS
376    NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedRowsAttribute];
377    if (index < [rows count])
378        return [rows objectAtIndex:index];
379    END_AX_OBJC_EXCEPTIONS
380
381    return 0;
382}
383
384AccessibilityUIElement AccessibilityUIElement::selectedChildAtIndex(unsigned index) const
385{
386    BEGIN_AX_OBJC_EXCEPTIONS
387    NSArray* array = [m_element accessibilityAttributeValue:NSAccessibilitySelectedChildrenAttribute];
388    if (index < [array count])
389        return [array objectAtIndex:index];
390    END_AX_OBJC_EXCEPTIONS
391
392    return 0;
393}
394
395unsigned AccessibilityUIElement::selectedChildrenCount() const
396{
397    BEGIN_AX_OBJC_EXCEPTIONS
398    return [m_element accessibilityArrayAttributeCount:NSAccessibilitySelectedChildrenAttribute];
399    END_AX_OBJC_EXCEPTIONS
400
401    return 0;
402}
403
404AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
405{
406    BEGIN_AX_OBJC_EXCEPTIONS
407    NSArray* rows = [m_element accessibilityAttributeValue:NSAccessibilitySelectedRowsAttribute];
408    if (index < [rows count])
409        return [rows objectAtIndex:index];
410    END_AX_OBJC_EXCEPTIONS
411
412    return 0;
413}
414
415AccessibilityUIElement AccessibilityUIElement::titleUIElement()
416{
417    BEGIN_AX_OBJC_EXCEPTIONS
418    id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityTitleUIElementAttribute];
419    if (accessibilityObject)
420        return AccessibilityUIElement(accessibilityObject);
421    END_AX_OBJC_EXCEPTIONS
422
423    return 0;
424}
425
426AccessibilityUIElement AccessibilityUIElement::parentElement()
427{
428    BEGIN_AX_OBJC_EXCEPTIONS
429    id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityParentAttribute];
430    if (accessibilityObject)
431        return AccessibilityUIElement(accessibilityObject);
432    END_AX_OBJC_EXCEPTIONS
433
434    return 0;
435}
436
437AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
438{
439    BEGIN_AX_OBJC_EXCEPTIONS
440    id accessibilityObject = [m_element accessibilityAttributeValue:NSAccessibilityDisclosedByRowAttribute];
441    if (accessibilityObject)
442        return AccessibilityUIElement(accessibilityObject);
443    END_AX_OBJC_EXCEPTIONS
444
445    return 0;
446}
447
448JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
449{
450    Vector<AccessibilityUIElement> linkedElements;
451    getLinkedUIElements(linkedElements);
452    return descriptionOfElements(linkedElements);
453}
454
455JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
456{
457    Vector<AccessibilityUIElement> linkElements;
458    getDocumentLinks(linkElements);
459    return descriptionOfElements(linkElements);
460}
461
462JSStringRef AccessibilityUIElement::attributesOfChildren()
463{
464    Vector<AccessibilityUIElement> children;
465    getChildren(children);
466    return descriptionOfElements(children);
467}
468
469JSStringRef AccessibilityUIElement::allAttributes()
470{
471    NSString* attributes = attributesOfElement(m_element);
472    return [attributes createJSStringRef];
473}
474
475JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
476{
477    BEGIN_AX_OBJC_EXCEPTIONS
478    id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
479    if ([value isKindOfClass:[NSString class]])
480        return [value createJSStringRef];
481    END_AX_OBJC_EXCEPTIONS
482
483    return 0;
484}
485
486bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
487{
488    BEGIN_AX_OBJC_EXCEPTIONS
489    id value = [m_element accessibilityAttributeValue:[NSString stringWithJSStringRef:attribute]];
490    if ([value isKindOfClass:[NSNumber class]])
491        return [value boolValue];
492    END_AX_OBJC_EXCEPTIONS
493
494    return false;
495}
496
497bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
498{
499    BEGIN_AX_OBJC_EXCEPTIONS
500    return [m_element accessibilityIsAttributeSettable:[NSString stringWithJSStringRef:attribute]];
501    END_AX_OBJC_EXCEPTIONS
502
503    return false;
504}
505
506bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
507{
508    BEGIN_AX_OBJC_EXCEPTIONS
509    return [[m_element accessibilityAttributeNames] containsObject:[NSString stringWithJSStringRef:attribute]];
510    END_AX_OBJC_EXCEPTIONS
511
512    return false;
513}
514
515JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
516{
517    NSArray* supportedParameterizedAttributes = [m_element accessibilityParameterizedAttributeNames];
518
519    NSMutableString* attributesString = [NSMutableString string];
520    for (NSUInteger i = 0; i < [supportedParameterizedAttributes count]; ++i) {
521        [attributesString appendFormat:@"%@\n", [supportedParameterizedAttributes objectAtIndex:i]];
522    }
523
524    return [attributesString createJSStringRef];
525}
526
527JSStringRef AccessibilityUIElement::role()
528{
529    BEGIN_AX_OBJC_EXCEPTIONS
530    NSString *role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleAttribute], m_element);
531    return concatenateAttributeAndValue(@"AXRole", role);
532    END_AX_OBJC_EXCEPTIONS
533
534    return 0;
535}
536
537JSStringRef AccessibilityUIElement::subrole()
538{
539    BEGIN_AX_OBJC_EXCEPTIONS
540    NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilitySubroleAttribute], m_element);
541    return concatenateAttributeAndValue(@"AXSubrole", role);
542    END_AX_OBJC_EXCEPTIONS
543
544    return 0;
545}
546
547JSStringRef AccessibilityUIElement::roleDescription()
548{
549    BEGIN_AX_OBJC_EXCEPTIONS
550    NSString* role = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute], m_element);
551    return concatenateAttributeAndValue(@"AXRoleDescription", role);
552    END_AX_OBJC_EXCEPTIONS
553
554    return 0;
555}
556
557JSStringRef AccessibilityUIElement::title()
558{
559    BEGIN_AX_OBJC_EXCEPTIONS
560    NSString* title = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityTitleAttribute], m_element);
561    return concatenateAttributeAndValue(@"AXTitle", title);
562    END_AX_OBJC_EXCEPTIONS
563
564    return 0;
565}
566
567JSStringRef AccessibilityUIElement::description()
568{
569    BEGIN_AX_OBJC_EXCEPTIONS
570    id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityDescriptionAttribute], m_element);
571    return concatenateAttributeAndValue(@"AXDescription", description);
572    END_AX_OBJC_EXCEPTIONS
573
574    return 0;
575}
576
577JSStringRef AccessibilityUIElement::orientation() const
578{
579    BEGIN_AX_OBJC_EXCEPTIONS
580    id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityOrientationAttribute], m_element);
581    return concatenateAttributeAndValue(@"AXOrientation", description);
582    END_AX_OBJC_EXCEPTIONS
583
584    return 0;
585}
586
587JSStringRef AccessibilityUIElement::stringValue()
588{
589    BEGIN_AX_OBJC_EXCEPTIONS
590    id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityValueAttribute], m_element);
591    return concatenateAttributeAndValue(@"AXValue", description);
592    END_AX_OBJC_EXCEPTIONS
593
594    return 0;
595}
596
597JSStringRef AccessibilityUIElement::language()
598{
599    BEGIN_AX_OBJC_EXCEPTIONS
600    id description = descriptionOfValue([m_element accessibilityAttributeValue:@"AXLanguage"], m_element);
601    return concatenateAttributeAndValue(@"AXLanguage", description);
602    END_AX_OBJC_EXCEPTIONS
603
604    return 0;
605}
606
607JSStringRef AccessibilityUIElement::helpText() const
608{
609    BEGIN_AX_OBJC_EXCEPTIONS
610    id description = descriptionOfValue([m_element accessibilityAttributeValue:NSAccessibilityHelpAttribute], m_element);
611    return concatenateAttributeAndValue(@"AXHelp", description);
612    END_AX_OBJC_EXCEPTIONS
613
614    return 0;
615}
616
617double AccessibilityUIElement::x()
618{
619    BEGIN_AX_OBJC_EXCEPTIONS
620    NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
621    return static_cast<double>([positionValue pointValue].x);
622    END_AX_OBJC_EXCEPTIONS
623
624    return 0.0f;
625}
626
627double AccessibilityUIElement::y()
628{
629    BEGIN_AX_OBJC_EXCEPTIONS
630    NSValue* positionValue = [m_element accessibilityAttributeValue:NSAccessibilityPositionAttribute];
631    return static_cast<double>([positionValue pointValue].y);
632    END_AX_OBJC_EXCEPTIONS
633
634    return 0.0f;
635}
636
637double AccessibilityUIElement::width()
638{
639    BEGIN_AX_OBJC_EXCEPTIONS
640    NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
641    return static_cast<double>([sizeValue sizeValue].width);
642    END_AX_OBJC_EXCEPTIONS
643
644    return 0.0f;
645}
646
647double AccessibilityUIElement::height()
648{
649    BEGIN_AX_OBJC_EXCEPTIONS
650    NSValue* sizeValue = [m_element accessibilityAttributeValue:NSAccessibilitySizeAttribute];
651    return static_cast<double>([sizeValue sizeValue].height);
652    END_AX_OBJC_EXCEPTIONS
653
654    return 0.0f;
655}
656
657double AccessibilityUIElement::clickPointX()
658{
659    BEGIN_AX_OBJC_EXCEPTIONS
660    NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
661    return static_cast<double>([positionValue pointValue].x);
662    END_AX_OBJC_EXCEPTIONS
663
664    return 0.0f;
665}
666
667double AccessibilityUIElement::clickPointY()
668{
669    BEGIN_AX_OBJC_EXCEPTIONS
670    NSValue* positionValue = [m_element accessibilityAttributeValue:@"AXClickPoint"];
671    return static_cast<double>([positionValue pointValue].y);
672    END_AX_OBJC_EXCEPTIONS
673
674    return 0.0f;
675}
676
677double AccessibilityUIElement::intValue() const
678{
679    BEGIN_AX_OBJC_EXCEPTIONS
680    id value = [m_element accessibilityAttributeValue:NSAccessibilityValueAttribute];
681    if ([value isKindOfClass:[NSNumber class]])
682        return [(NSNumber*)value doubleValue];
683    END_AX_OBJC_EXCEPTIONS
684
685    return 0.0f;
686}
687
688double AccessibilityUIElement::minValue()
689{
690    BEGIN_AX_OBJC_EXCEPTIONS
691    id value = [m_element accessibilityAttributeValue:NSAccessibilityMinValueAttribute];
692    if ([value isKindOfClass:[NSNumber class]])
693        return [(NSNumber*)value doubleValue];
694    END_AX_OBJC_EXCEPTIONS
695
696    return 0.0f;
697}
698
699double AccessibilityUIElement::maxValue()
700{
701    BEGIN_AX_OBJC_EXCEPTIONS
702    id value = [m_element accessibilityAttributeValue:NSAccessibilityMaxValueAttribute];
703    if ([value isKindOfClass:[NSNumber class]])
704        return [(NSNumber*)value doubleValue];
705    END_AX_OBJC_EXCEPTIONS
706
707    return 0.0;
708}
709
710JSStringRef AccessibilityUIElement::valueDescription()
711{
712    BEGIN_AX_OBJC_EXCEPTIONS
713    NSString* valueDescription = [m_element accessibilityAttributeValue:NSAccessibilityValueDescriptionAttribute];
714    if ([valueDescription isKindOfClass:[NSString class]])
715         return [valueDescription createJSStringRef];
716
717    END_AX_OBJC_EXCEPTIONS
718    return 0;
719}
720
721int AccessibilityUIElement::insertionPointLineNumber()
722{
723    BEGIN_AX_OBJC_EXCEPTIONS
724    id value = [m_element accessibilityAttributeValue:NSAccessibilityInsertionPointLineNumberAttribute];
725    if ([value isKindOfClass:[NSNumber class]])
726        return [(NSNumber *)value intValue];
727    END_AX_OBJC_EXCEPTIONS
728
729    return -1;
730}
731
732bool AccessibilityUIElement::isActionSupported(JSStringRef action)
733{
734    BEGIN_AX_OBJC_EXCEPTIONS
735    NSArray* actions = [m_element accessibilityActionNames];
736    return [actions containsObject:[NSString stringWithJSStringRef:action]];
737    END_AX_OBJC_EXCEPTIONS
738
739    return false;
740}
741
742bool AccessibilityUIElement::isEnabled()
743{
744    BEGIN_AX_OBJC_EXCEPTIONS
745    id value = [m_element accessibilityAttributeValue:NSAccessibilityEnabledAttribute];
746    if ([value isKindOfClass:[NSNumber class]])
747        return [value boolValue];
748    END_AX_OBJC_EXCEPTIONS
749
750    return false;
751}
752
753bool AccessibilityUIElement::isRequired() const
754{
755    BEGIN_AX_OBJC_EXCEPTIONS
756    id value = [m_element accessibilityAttributeValue:@"AXRequired"];
757    if ([value isKindOfClass:[NSNumber class]])
758        return [value boolValue];
759    END_AX_OBJC_EXCEPTIONS
760
761    return false;
762}
763
764bool AccessibilityUIElement::isFocused() const
765{
766    // FIXME: implement
767    return false;
768}
769
770bool AccessibilityUIElement::isSelected() const
771{
772    BEGIN_AX_OBJC_EXCEPTIONS
773    id value = [m_element accessibilityAttributeValue:NSAccessibilitySelectedAttribute];
774    if ([value isKindOfClass:[NSNumber class]])
775        return [value boolValue];
776    END_AX_OBJC_EXCEPTIONS
777
778    return false;
779}
780
781bool AccessibilityUIElement::isExpanded() const
782{
783    BEGIN_AX_OBJC_EXCEPTIONS
784    id value = [m_element accessibilityAttributeValue:NSAccessibilityExpandedAttribute];
785    if ([value isKindOfClass:[NSNumber class]])
786        return [value boolValue];
787    END_AX_OBJC_EXCEPTIONS
788
789    return false;
790}
791
792bool AccessibilityUIElement::isChecked() const
793{
794    // On the Mac, intValue()==1 if a a checkable control is checked.
795    return intValue() == 1;
796}
797
798int AccessibilityUIElement::hierarchicalLevel() const
799{
800    BEGIN_AX_OBJC_EXCEPTIONS
801    id value = [m_element accessibilityAttributeValue:NSAccessibilityDisclosureLevelAttribute];
802    if ([value isKindOfClass:[NSNumber class]])
803        return [value intValue];
804    END_AX_OBJC_EXCEPTIONS
805
806    return 0;
807}
808
809JSStringRef AccessibilityUIElement::speak()
810{
811    BEGIN_AX_OBJC_EXCEPTIONS
812    id value = [m_element accessibilityAttributeValue:@"AXDRTSpeechAttribute"];
813    if ([value isKindOfClass:[NSString class]])
814        return [value createJSStringRef];
815    END_AX_OBJC_EXCEPTIONS
816
817    return 0;
818}
819
820bool AccessibilityUIElement::ariaIsGrabbed() const
821{
822    BEGIN_AX_OBJC_EXCEPTIONS
823    id value = [m_element accessibilityAttributeValue:NSAccessibilityGrabbedAttribute];
824    if ([value isKindOfClass:[NSNumber class]])
825        return [value boolValue];
826    END_AX_OBJC_EXCEPTIONS
827
828    return false;
829}
830
831JSStringRef AccessibilityUIElement::ariaDropEffects() const
832{
833    BEGIN_AX_OBJC_EXCEPTIONS
834    id value = [m_element accessibilityAttributeValue:NSAccessibilityDropEffectsAttribute];
835    if (![value isKindOfClass:[NSArray class]])
836        return 0;
837
838    NSMutableString* dropEffects = [NSMutableString string];
839    NSInteger length = [value count];
840    for (NSInteger k = 0; k < length; ++k) {
841        [dropEffects appendString:[value objectAtIndex:k]];
842        if (k < length - 1)
843            [dropEffects appendString:@","];
844    }
845
846    return [dropEffects createJSStringRef];
847    END_AX_OBJC_EXCEPTIONS
848
849    return 0;
850}
851
852// parameterized attributes
853int AccessibilityUIElement::lineForIndex(int index)
854{
855    BEGIN_AX_OBJC_EXCEPTIONS
856    id value = [m_element accessibilityAttributeValue:NSAccessibilityLineForIndexParameterizedAttribute forParameter:[NSNumber numberWithInt:index]];
857    if ([value isKindOfClass:[NSNumber class]])
858        return [(NSNumber *)value intValue];
859    END_AX_OBJC_EXCEPTIONS
860
861    return -1;
862}
863
864JSStringRef AccessibilityUIElement::rangeForLine(int line)
865{
866    BEGIN_AX_OBJC_EXCEPTIONS
867    id value = [m_element accessibilityAttributeValue:NSAccessibilityRangeForLineParameterizedAttribute forParameter:[NSNumber numberWithInt:line]];
868    if ([value isKindOfClass:[NSValue class]]) {
869        return [NSStringFromRange([value rangeValue]) createJSStringRef];
870    }
871    END_AX_OBJC_EXCEPTIONS
872
873    return 0;
874}
875
876JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
877{
878    NSRange range = NSMakeRange(location, length);
879    BEGIN_AX_OBJC_EXCEPTIONS
880    id value = [m_element accessibilityAttributeValue:NSAccessibilityBoundsForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
881    NSRect rect = NSMakeRect(0,0,0,0);
882    if ([value isKindOfClass:[NSValue class]])
883        rect = [value rectValue];
884
885    // don't return position information because it is platform dependent
886    NSMutableString* boundsDescription = [NSMutableString stringWithFormat:@"{{%f, %f}, {%f, %f}}",-1.0f,-1.0f,rect.size.width,rect.size.height];
887    return [boundsDescription createJSStringRef];
888    END_AX_OBJC_EXCEPTIONS
889
890    return 0;
891}
892
893JSStringRef AccessibilityUIElement::stringForRange(unsigned location, unsigned length)
894{
895    NSRange range = NSMakeRange(location, length);
896    BEGIN_AX_OBJC_EXCEPTIONS
897    id string = [m_element accessibilityAttributeValue:NSAccessibilityStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
898    if (![string isKindOfClass:[NSString class]])
899        return 0;
900
901    return [string createJSStringRef];
902    END_AX_OBJC_EXCEPTIONS
903
904    return 0;
905}
906
907JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned location, unsigned length)
908{
909    NSRange range = NSMakeRange(location, length);
910    BEGIN_AX_OBJC_EXCEPTIONS
911    NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
912    if (![string isKindOfClass:[NSAttributedString class]])
913        return 0;
914
915    NSString* stringWithAttrs = [string description];
916    return [stringWithAttrs createJSStringRef];
917    END_AX_OBJC_EXCEPTIONS
918
919    return 0;
920}
921
922bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned location, unsigned length)
923{
924    NSRange range = NSMakeRange(location, length);
925    BEGIN_AX_OBJC_EXCEPTIONS
926    NSAttributedString* string = [m_element accessibilityAttributeValue:NSAccessibilityAttributedStringForRangeParameterizedAttribute forParameter:[NSValue valueWithRange:range]];
927    if (![string isKindOfClass:[NSAttributedString class]])
928        return false;
929
930    NSDictionary* attrs = [string attributesAtIndex:0 effectiveRange:nil];
931    if([[attrs objectForKey:NSAccessibilityMisspelledTextAttribute] boolValue])
932        return true;
933    END_AX_OBJC_EXCEPTIONS
934
935    return false;
936}
937
938JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
939{
940    // not yet defined in AppKit... odd
941    BEGIN_AX_OBJC_EXCEPTIONS
942    NSArray* columnHeadersArray = [m_element accessibilityAttributeValue:@"AXColumnHeaderUIElements"];
943    Vector<AccessibilityUIElement> columnHeadersVector;
944    convertNSArrayToVector(columnHeadersArray, columnHeadersVector);
945    return descriptionOfElements(columnHeadersVector);
946    END_AX_OBJC_EXCEPTIONS
947
948    return 0;
949}
950
951JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
952{
953    BEGIN_AX_OBJC_EXCEPTIONS
954    NSArray* rowHeadersArray = [m_element accessibilityAttributeValue:@"AXRowHeaderUIElements"];
955    Vector<AccessibilityUIElement> rowHeadersVector;
956    convertNSArrayToVector(rowHeadersArray, rowHeadersVector);
957    return descriptionOfElements(rowHeadersVector);
958    END_AX_OBJC_EXCEPTIONS
959
960    return 0;
961}
962
963JSStringRef AccessibilityUIElement::attributesOfColumns()
964{
965    BEGIN_AX_OBJC_EXCEPTIONS
966    NSArray* columnsArray = [m_element accessibilityAttributeValue:NSAccessibilityColumnsAttribute];
967    Vector<AccessibilityUIElement> columnsVector;
968    convertNSArrayToVector(columnsArray, columnsVector);
969    return descriptionOfElements(columnsVector);
970    END_AX_OBJC_EXCEPTIONS
971
972    return 0;
973}
974
975JSStringRef AccessibilityUIElement::attributesOfRows()
976{
977    BEGIN_AX_OBJC_EXCEPTIONS
978    NSArray* rowsArray = [m_element accessibilityAttributeValue:NSAccessibilityRowsAttribute];
979    Vector<AccessibilityUIElement> rowsVector;
980    convertNSArrayToVector(rowsArray, rowsVector);
981    return descriptionOfElements(rowsVector);
982    END_AX_OBJC_EXCEPTIONS
983
984    return 0;
985}
986
987JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
988{
989    BEGIN_AX_OBJC_EXCEPTIONS
990    NSArray* cellsArray = [m_element accessibilityAttributeValue:@"AXVisibleCells"];
991    Vector<AccessibilityUIElement> cellsVector;
992    convertNSArrayToVector(cellsArray, cellsVector);
993    return descriptionOfElements(cellsVector);
994    END_AX_OBJC_EXCEPTIONS
995
996    return 0;
997}
998
999JSStringRef AccessibilityUIElement::attributesOfHeader()
1000{
1001    BEGIN_AX_OBJC_EXCEPTIONS
1002    id headerObject = [m_element accessibilityAttributeValue:NSAccessibilityHeaderAttribute];
1003    if (!headerObject)
1004        return [@"" createJSStringRef];
1005
1006    Vector<AccessibilityUIElement> headerVector;
1007    headerVector.append(headerObject);
1008    return descriptionOfElements(headerVector);
1009    END_AX_OBJC_EXCEPTIONS
1010
1011    return 0;
1012}
1013
1014int AccessibilityUIElement::rowCount()
1015{
1016    BEGIN_AX_OBJC_EXCEPTIONS
1017    return [m_element accessibilityArrayAttributeCount:NSAccessibilityRowsAttribute];
1018    END_AX_OBJC_EXCEPTIONS
1019
1020    return 0;
1021}
1022
1023int AccessibilityUIElement::columnCount()
1024{
1025    BEGIN_AX_OBJC_EXCEPTIONS
1026    return [m_element accessibilityArrayAttributeCount:NSAccessibilityColumnsAttribute];
1027    END_AX_OBJC_EXCEPTIONS
1028
1029    return 0;
1030}
1031
1032int AccessibilityUIElement::indexInTable()
1033{
1034    BEGIN_AX_OBJC_EXCEPTIONS
1035    NSNumber* indexNumber = [m_element accessibilityAttributeValue:NSAccessibilityIndexAttribute];
1036    if (indexNumber)
1037        return [indexNumber intValue];
1038    END_AX_OBJC_EXCEPTIONS
1039
1040    return -1;
1041}
1042
1043JSStringRef AccessibilityUIElement::rowIndexRange()
1044{
1045    NSRange range = NSMakeRange(0,0);
1046    BEGIN_AX_OBJC_EXCEPTIONS
1047    NSValue* indexRange = [m_element accessibilityAttributeValue:@"AXRowIndexRange"];
1048    if (indexRange)
1049        range = [indexRange rangeValue];
1050    NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length];
1051    return [rangeDescription createJSStringRef];
1052    END_AX_OBJC_EXCEPTIONS
1053
1054    return 0;
1055}
1056
1057JSStringRef AccessibilityUIElement::columnIndexRange()
1058{
1059    NSRange range = NSMakeRange(0,0);
1060    BEGIN_AX_OBJC_EXCEPTIONS
1061    NSNumber* indexRange = [m_element accessibilityAttributeValue:@"AXColumnIndexRange"];
1062    if (indexRange)
1063        range = [indexRange rangeValue];
1064    NSMutableString* rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length];
1065    return [rangeDescription createJSStringRef];
1066    END_AX_OBJC_EXCEPTIONS
1067
1068    return 0;
1069}
1070
1071AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned col, unsigned row)
1072{
1073    NSArray *colRowArray = [NSArray arrayWithObjects:[NSNumber numberWithUnsignedInt:col], [NSNumber numberWithUnsignedInt:row], nil];
1074    BEGIN_AX_OBJC_EXCEPTIONS
1075    return [m_element accessibilityAttributeValue:@"AXCellForColumnAndRow" forParameter:colRowArray];
1076    END_AX_OBJC_EXCEPTIONS
1077
1078    return 0;
1079}
1080
1081JSStringRef AccessibilityUIElement::selectedTextRange()
1082{
1083    NSRange range = NSMakeRange(NSNotFound, 0);
1084    BEGIN_AX_OBJC_EXCEPTIONS
1085    NSValue *indexRange = [m_element accessibilityAttributeValue:NSAccessibilitySelectedTextRangeAttribute];
1086    if (indexRange)
1087        range = [indexRange rangeValue];
1088    NSMutableString *rangeDescription = [NSMutableString stringWithFormat:@"{%d, %d}",range.location, range.length];
1089    return [rangeDescription createJSStringRef];
1090    END_AX_OBJC_EXCEPTIONS
1091
1092    return 0;
1093}
1094
1095void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
1096{
1097    NSRange textRange = NSMakeRange(location, length);
1098    NSValue *textRangeValue = [NSValue valueWithRange:textRange];
1099    BEGIN_AX_OBJC_EXCEPTIONS
1100    [m_element accessibilitySetValue:textRangeValue forAttribute:NSAccessibilitySelectedTextRangeAttribute];
1101    END_AX_OBJC_EXCEPTIONS
1102}
1103
1104void AccessibilityUIElement::increment()
1105{
1106    BEGIN_AX_OBJC_EXCEPTIONS
1107    [m_element accessibilityPerformAction:NSAccessibilityIncrementAction];
1108    END_AX_OBJC_EXCEPTIONS
1109}
1110
1111void AccessibilityUIElement::decrement()
1112{
1113    BEGIN_AX_OBJC_EXCEPTIONS
1114    [m_element accessibilityPerformAction:NSAccessibilityDecrementAction];
1115    END_AX_OBJC_EXCEPTIONS
1116}
1117
1118void AccessibilityUIElement::showMenu()
1119{
1120    BEGIN_AX_OBJC_EXCEPTIONS
1121    [m_element accessibilityPerformAction:NSAccessibilityShowMenuAction];
1122    END_AX_OBJC_EXCEPTIONS
1123}
1124
1125void AccessibilityUIElement::press()
1126{
1127    BEGIN_AX_OBJC_EXCEPTIONS
1128    [m_element accessibilityPerformAction:NSAccessibilityPressAction];
1129    END_AX_OBJC_EXCEPTIONS
1130}
1131
1132void AccessibilityUIElement::setSelectedChild(AccessibilityUIElement* element) const
1133{
1134    BEGIN_AX_OBJC_EXCEPTIONS
1135    NSArray* array = [NSArray arrayWithObject:element->platformUIElement()];
1136    [m_element accessibilitySetValue:array forAttribute:NSAccessibilitySelectedChildrenAttribute];
1137    END_AX_OBJC_EXCEPTIONS
1138}
1139
1140JSStringRef AccessibilityUIElement::accessibilityValue() const
1141{
1142    // FIXME: implement
1143    return JSStringCreateWithCharacters(0, 0);
1144}
1145
1146JSStringRef AccessibilityUIElement::documentEncoding()
1147{
1148    return JSStringCreateWithCharacters(0, 0);
1149}
1150
1151JSStringRef AccessibilityUIElement::documentURI()
1152{
1153    return JSStringCreateWithCharacters(0, 0);
1154}
1155
1156JSStringRef AccessibilityUIElement::url()
1157{
1158    BEGIN_AX_OBJC_EXCEPTIONS
1159    NSURL *url = [m_element accessibilityAttributeValue:NSAccessibilityURLAttribute];
1160    return [[url absoluteString] createJSStringRef];
1161    END_AX_OBJC_EXCEPTIONS
1162
1163    return nil;
1164}
1165
1166bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
1167{
1168    if (!functionCallback)
1169        return false;
1170
1171    // Mac programmers should not be adding more than one notification listener per element.
1172    // Other platforms may be different.
1173    if (m_notificationHandler)
1174        return false;
1175    m_notificationHandler = [[AccessibilityNotificationHandler alloc] initWithPlatformElement:platformUIElement()];
1176    [m_notificationHandler setCallback:functionCallback];
1177
1178    return true;
1179}
1180
1181void AccessibilityUIElement::removeNotificationListener()
1182{
1183    // Mac programmers should not be trying to remove a listener that's already removed.
1184    ASSERT(m_notificationHandler);
1185
1186    [m_notificationHandler release];
1187    m_notificationHandler = nil;
1188}
1189
1190bool AccessibilityUIElement::isFocusable() const
1191{
1192    // FIXME: implement
1193    return false;
1194}
1195
1196bool AccessibilityUIElement::isSelectable() const
1197{
1198    // FIXME: implement
1199    return false;
1200}
1201
1202bool AccessibilityUIElement::isMultiSelectable() const
1203{
1204    // FIXME: implement
1205    return false;
1206}
1207
1208bool AccessibilityUIElement::isVisible() const
1209{
1210    // FIXME: implement
1211    return false;
1212}
1213
1214bool AccessibilityUIElement::isOffScreen() const
1215{
1216    // FIXME: implement
1217    return false;
1218}
1219
1220bool AccessibilityUIElement::isCollapsed() const
1221{
1222    // FIXME: implement
1223    return false;
1224}
1225
1226bool AccessibilityUIElement::isIgnored() const
1227{
1228    BOOL result = NO;
1229    BEGIN_AX_OBJC_EXCEPTIONS
1230    result = [m_element accessibilityIsIgnored];
1231    END_AX_OBJC_EXCEPTIONS
1232    return result;
1233}
1234
1235bool AccessibilityUIElement::hasPopup() const
1236{
1237    BEGIN_AX_OBJC_EXCEPTIONS
1238    id value = [m_element accessibilityAttributeValue:@"AXHasPopup"];
1239    if ([value isKindOfClass:[NSNumber class]])
1240        return [value boolValue];
1241    END_AX_OBJC_EXCEPTIONS
1242
1243    return false;
1244}
1245
1246void AccessibilityUIElement::takeFocus()
1247{
1248    // FIXME: implement
1249}
1250
1251void AccessibilityUIElement::takeSelection()
1252{
1253    // FIXME: implement
1254}
1255
1256void AccessibilityUIElement::addSelection()
1257{
1258    // FIXME: implement
1259}
1260
1261void AccessibilityUIElement::removeSelection()
1262{
1263    // FIXME: implement
1264}
1265
1266#if SUPPORTS_AX_TEXTMARKERS
1267
1268// Text markers
1269AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForElement(AccessibilityUIElement* element)
1270{
1271    BEGIN_AX_OBJC_EXCEPTIONS
1272    id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUIElement" forParameter:element->platformUIElement()];
1273    return AccessibilityTextMarkerRange(textMarkerRange);
1274    END_AX_OBJC_EXCEPTIONS
1275
1276    return 0;
1277}
1278
1279int AccessibilityUIElement::textMarkerRangeLength(AccessibilityTextMarkerRange* range)
1280{
1281    BEGIN_AX_OBJC_EXCEPTIONS
1282    NSNumber* lengthValue = [m_element accessibilityAttributeValue:@"AXLengthForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1283    return [lengthValue intValue];
1284    END_AX_OBJC_EXCEPTIONS
1285
1286    return 0;
1287}
1288
1289
1290AccessibilityTextMarkerRange AccessibilityUIElement::textMarkerRangeForMarkers(AccessibilityTextMarker* startMarker, AccessibilityTextMarker* endMarker)
1291{
1292    BEGIN_AX_OBJC_EXCEPTIONS
1293    NSArray* textMarkers = [NSArray arrayWithObjects:(id)startMarker->platformTextMarker(), (id)endMarker->platformTextMarker(), nil];
1294    id textMarkerRange = [m_element accessibilityAttributeValue:@"AXTextMarkerRangeForUnorderedTextMarkers" forParameter:textMarkers];
1295    return AccessibilityTextMarkerRange(textMarkerRange);
1296    END_AX_OBJC_EXCEPTIONS
1297
1298    return 0;
1299}
1300
1301AccessibilityTextMarker AccessibilityUIElement::startTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1302{
1303    BEGIN_AX_OBJC_EXCEPTIONS
1304    id textMarker = [m_element accessibilityAttributeValue:@"AXStartTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1305    return AccessibilityTextMarker(textMarker);
1306    END_AX_OBJC_EXCEPTIONS
1307
1308    return 0;
1309}
1310
1311AccessibilityTextMarker AccessibilityUIElement::endTextMarkerForTextMarkerRange(AccessibilityTextMarkerRange* range)
1312{
1313    BEGIN_AX_OBJC_EXCEPTIONS
1314    id textMarker = [m_element accessibilityAttributeValue:@"AXEndTextMarkerForTextMarkerRange" forParameter:(id)range->platformTextMarkerRange()];
1315    return AccessibilityTextMarker(textMarker);
1316    END_AX_OBJC_EXCEPTIONS
1317
1318    return 0;
1319}
1320
1321AccessibilityTextMarker AccessibilityUIElement::textMarkerForPoint(int x, int y)
1322{
1323    BEGIN_AX_OBJC_EXCEPTIONS
1324    id textMarker = [m_element accessibilityAttributeValue:@"AXTextMarkerForPosition" forParameter:[NSValue valueWithPoint:NSMakePoint(x, y)]];
1325    return AccessibilityTextMarker(textMarker);
1326    END_AX_OBJC_EXCEPTIONS
1327
1328    return 0;
1329}
1330
1331AccessibilityUIElement AccessibilityUIElement::accessibilityElementForTextMarker(AccessibilityTextMarker* marker)
1332{
1333    BEGIN_AX_OBJC_EXCEPTIONS
1334    id uiElement = [m_element accessibilityAttributeValue:@"AXUIElementForTextMarker" forParameter:(id)marker->platformTextMarker()];
1335    return AccessibilityUIElement(uiElement);
1336    END_AX_OBJC_EXCEPTIONS
1337
1338    return 0;
1339}
1340
1341#endif // SUPPORTS_AX_TEXTMARKERS
1342