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