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