e9b7fc2d93066a17efa1be8ef467d301a25e1b4e
[WebKit-https.git] / Tools / DumpRenderTree / win / AccessibilityUIElementWin.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "AccessibilityUIElement.h"
28
29 #include "AccessibilityController.h"
30 #include "DumpRenderTree.h"
31 #include "FrameLoadDelegate.h"
32 #include <JavaScriptCore/JSStringRef.h>
33 #include <tchar.h>
34 #include <string>
35
36 using std::wstring;
37
38 static COMPtr<IAccessibleComparable> comparableObject(IAccessible* accessible)
39 {
40     COMPtr<IServiceProvider> serviceProvider(Query, accessible);
41     if (!serviceProvider)
42         return 0;
43     COMPtr<IAccessibleComparable> comparable;
44     serviceProvider->QueryService(SID_AccessibleComparable, __uuidof(IAccessibleComparable), reinterpret_cast<void**>(&comparable));
45     return comparable;
46 }
47
48 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
49     : m_element(element)
50 {
51 }
52
53 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
54     : m_element(other.m_element)
55 {
56 }
57
58 AccessibilityUIElement::~AccessibilityUIElement()
59 {
60 }
61
62 bool AccessibilityUIElement::isEqual(AccessibilityUIElement* otherElement)
63 {
64     COMPtr<IAccessibleComparable> comparable = comparableObject(m_element.get());
65     COMPtr<IAccessibleComparable> otherComparable = comparableObject(otherElement->m_element.get());
66     if (!comparable || !otherComparable)
67         return false;
68     BOOL isSame = FALSE;
69     if (FAILED(comparable->isSameObject(otherComparable.get(), &isSame)))
70         return false;
71     return isSame;
72 }
73
74 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>&)
75 {
76 }
77
78 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
79 {
80 }
81
82 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
83 {
84     long childCount;
85     if (FAILED(m_element->get_accChildCount(&childCount)))
86         return;
87     for (long i = 0; i < childCount; ++i)
88         children.append(getChildAtIndex(i));
89 }
90
91 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
92 {
93     long childCount;
94     unsigned appendedCount = 0;
95     if (FAILED(m_element->get_accChildCount(&childCount)))
96         return;
97     for (long i = location; i < childCount && appendedCount < length; ++i, ++appendedCount)
98         elementVector.append(getChildAtIndex(i));
99 }
100
101 int AccessibilityUIElement::childrenCount()
102 {
103     long childCount;
104     m_element->get_accChildCount(&childCount);
105     return childCount;
106 }
107
108 int AccessibilityUIElement::rowCount()
109 {
110     // FIXME: implement
111     return 0;
112 }
113  
114 int AccessibilityUIElement::columnCount()
115 {
116     // FIXME: implement
117     return 0;
118 }
119
120 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
121 {
122     return 0;
123 }
124
125 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
126 {
127     // FIXME: implement
128     return 0;
129 }
130
131 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
132 {
133     COMPtr<IDispatch> child;
134     VARIANT vChild;
135     ::VariantInit(&vChild);
136     V_VT(&vChild) = VT_I4;
137     // In MSAA, index 0 is the object itself.
138     V_I4(&vChild) = index + 1;
139     if (FAILED(m_element->get_accChild(vChild, &child)))
140         return 0;
141     return COMPtr<IAccessible>(Query, child);
142 }
143
144 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
145
146     // FIXME: implement
147     return 0;
148 }
149
150 JSStringRef AccessibilityUIElement::allAttributes()
151 {
152     return JSStringCreateWithCharacters(0, 0);
153 }
154
155 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
156 {
157     return JSStringCreateWithCharacters(0, 0);
158 }
159
160 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
161 {
162     return JSStringCreateWithCharacters(0, 0);
163 }
164
165 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
166 {
167     return 0;
168 }
169
170 AccessibilityUIElement AccessibilityUIElement::parentElement()
171 {
172     COMPtr<IDispatch> parent;
173     m_element->get_accParent(&parent);
174
175     COMPtr<IAccessible> parentAccessible(Query, parent);
176     return parentAccessible;
177 }
178
179 JSStringRef AccessibilityUIElement::attributesOfChildren()
180 {
181     return JSStringCreateWithCharacters(0, 0);
182 }
183
184 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
185 {
186     return JSStringCreateWithCharacters(0, 0);
187 }
188
189 static VARIANT& self()
190 {
191     static VARIANT vSelf;
192     static bool haveInitialized;
193
194     if (!haveInitialized) {
195         ::VariantInit(&vSelf);
196         V_VT(&vSelf) = VT_I4;
197         V_I4(&vSelf) = CHILDID_SELF;
198     }
199     return vSelf;
200 }
201
202 JSStringRef AccessibilityUIElement::role()
203 {
204     VARIANT vRole;
205     if (FAILED(m_element->get_accRole(self(), &vRole)))
206         return JSStringCreateWithCharacters(0, 0);
207
208     ASSERT(V_VT(&vRole) == VT_I4 || V_VT(&vRole) == VT_BSTR);
209
210     wstring result;
211     if (V_VT(&vRole) == VT_I4) {
212         unsigned roleTextLength = ::GetRoleText(V_I4(&vRole), 0, 0) + 1;
213
214         Vector<TCHAR> roleText(roleTextLength);
215
216         ::GetRoleText(V_I4(&vRole), roleText.data(), roleTextLength);
217
218         result = roleText.data();
219     } else if (V_VT(&vRole) == VT_BSTR)
220         result = wstring(V_BSTR(&vRole), ::SysStringLen(V_BSTR(&vRole)));
221
222     ::VariantClear(&vRole);
223
224     return JSStringCreateWithCharacters(result.data(), result.length());
225 }
226
227 JSStringRef AccessibilityUIElement::subrole()
228 {
229     return 0;
230 }
231
232 JSStringRef AccessibilityUIElement::roleDescription()
233 {
234     return 0;
235 }
236
237 JSStringRef AccessibilityUIElement::title()
238 {
239     BSTR titleBSTR;
240     if (FAILED(m_element->get_accName(self(), &titleBSTR)) || !titleBSTR)
241         return JSStringCreateWithCharacters(0, 0);
242     wstring title(titleBSTR, SysStringLen(titleBSTR));
243     ::SysFreeString(titleBSTR);
244     return JSStringCreateWithCharacters(title.data(), title.length());
245 }
246
247 JSStringRef AccessibilityUIElement::description()
248 {
249     BSTR descriptionBSTR;
250     if (FAILED(m_element->get_accDescription(self(), &descriptionBSTR)) || !descriptionBSTR)
251         return JSStringCreateWithCharacters(0, 0);
252     wstring description(descriptionBSTR, SysStringLen(descriptionBSTR));
253     ::SysFreeString(descriptionBSTR);
254     return JSStringCreateWithCharacters(description.data(), description.length());
255 }
256
257 JSStringRef AccessibilityUIElement::stringValue()
258 {
259     return JSStringCreateWithCharacters(0, 0);
260 }
261
262 JSStringRef AccessibilityUIElement::language()
263 {
264     return JSStringCreateWithCharacters(0, 0);
265 }
266
267 JSStringRef AccessibilityUIElement::helpText() const
268 {
269     return 0;
270 }
271
272 double AccessibilityUIElement::x()
273 {
274     long x, y, width, height;
275     if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
276         return 0;
277     return x;
278 }
279
280 double AccessibilityUIElement::y()
281 {
282     long x, y, width, height;
283     if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
284         return 0;
285     return y;
286 }
287
288 double AccessibilityUIElement::width()
289 {
290     long x, y, width, height;
291     if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
292         return 0;
293     return width;
294 }
295
296 double AccessibilityUIElement::height()
297 {
298     long x, y, width, height;
299     if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
300         return 0;
301     return height;
302 }
303
304 double AccessibilityUIElement::clickPointX()
305 {
306     return 0;
307 }
308
309 double AccessibilityUIElement::clickPointY()
310 {
311     return 0;
312 }
313
314 JSStringRef AccessibilityUIElement::valueDescription()
315 {
316     return 0;
317 }
318
319 static DWORD accessibilityState(COMPtr<IAccessible> element)
320 {
321     VARIANT state;
322     element->get_accState(self(), &state);
323
324     ASSERT(V_VT(&state) == VT_I4);
325
326     DWORD result = state.lVal;
327     VariantClear(&state);
328
329     return result;
330 }
331
332 bool AccessibilityUIElement::isFocused() const
333 {
334     // FIXME: implement
335     return false;
336 }
337
338 bool AccessibilityUIElement::isSelected() const
339 {
340     DWORD state = accessibilityState(m_element);
341     return (state & STATE_SYSTEM_SELECTED) == STATE_SYSTEM_SELECTED;
342 }
343
344 int AccessibilityUIElement::hierarchicalLevel() const
345 {
346     return 0;
347 }
348
349 bool AccessibilityUIElement::ariaIsGrabbed() const
350 {
351     return false;
352 }
353  
354 JSStringRef AccessibilityUIElement::ariaDropEffects() const
355 {
356     return 0;
357 }
358
359 bool AccessibilityUIElement::isExpanded() const
360 {
361     return false;
362 }
363
364 bool AccessibilityUIElement::isChecked() const
365 {
366     VARIANT vState;
367     if (FAILED(m_element->get_accState(self(), &vState)))
368         return false;
369
370     return vState.lVal & STATE_SYSTEM_CHECKED;
371 }
372
373 JSStringRef AccessibilityUIElement::orientation() const
374 {
375     return 0;
376 }
377
378 double AccessibilityUIElement::intValue() const
379 {
380     BSTR valueBSTR;
381     if (FAILED(m_element->get_accValue(self(), &valueBSTR)) || !valueBSTR)
382         return 0;
383     wstring value(valueBSTR, SysStringLen(valueBSTR));
384     ::SysFreeString(valueBSTR);
385     TCHAR* ignored;
386     return _tcstod(value.data(), &ignored);
387 }
388
389 double AccessibilityUIElement::minValue()
390 {
391     return 0;
392 }
393
394 double AccessibilityUIElement::maxValue()
395 {
396     return 0;
397 }
398
399 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
400 {
401     return false;
402 }
403
404 bool AccessibilityUIElement::isEnabled()
405 {
406     DWORD state = accessibilityState(m_element);
407     return (state & STATE_SYSTEM_UNAVAILABLE) != STATE_SYSTEM_UNAVAILABLE;
408 }
409
410 bool AccessibilityUIElement::isRequired() const
411 {
412     return false;
413 }
414
415
416 int AccessibilityUIElement::insertionPointLineNumber()
417 {
418     return 0;
419 }
420
421 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
422 {
423     return JSStringCreateWithCharacters(0, 0);
424 }
425
426 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
427 {
428     return JSStringCreateWithCharacters(0, 0);
429 }
430
431 JSStringRef AccessibilityUIElement::attributesOfColumns()
432 {
433     return JSStringCreateWithCharacters(0, 0);
434 }
435
436 JSStringRef AccessibilityUIElement::attributesOfRows()
437 {
438     return JSStringCreateWithCharacters(0, 0);
439 }
440
441 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
442 {
443     return JSStringCreateWithCharacters(0, 0);
444 }
445
446 JSStringRef AccessibilityUIElement::attributesOfHeader()
447 {
448     return JSStringCreateWithCharacters(0, 0);
449 }
450
451 int AccessibilityUIElement::indexInTable()
452 {
453     return 0;
454 }
455
456 JSStringRef AccessibilityUIElement::rowIndexRange()
457 {
458     return JSStringCreateWithCharacters(0, 0);
459 }
460
461 JSStringRef AccessibilityUIElement::columnIndexRange()
462 {
463     return JSStringCreateWithCharacters(0, 0);
464 }
465
466 int AccessibilityUIElement::lineForIndex(int)
467 {
468     return 0;
469 }
470
471 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
472 {
473     return JSStringCreateWithCharacters(0, 0);
474 }
475
476 JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned)
477 {
478     return JSStringCreateWithCharacters(0, 0);
479 }
480
481 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
482 {
483     return JSStringCreateWithCharacters(0, 0);
484 }
485
486 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned, unsigned)
487 {
488     return false;
489 }
490
491 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
492 {
493     return 0;
494 }
495
496 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
497 {
498     return 0;
499 }
500
501 JSStringRef AccessibilityUIElement::selectedTextRange()
502 {
503     return JSStringCreateWithCharacters(0, 0);    
504 }
505
506 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
507 {
508 }
509
510 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
511 {
512     // FIXME: implement
513     return JSStringCreateWithCharacters(0, 0);
514 }
515
516 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
517 {
518     // FIXME: implement
519     return 0;
520 }
521
522 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
523 {
524     // FIXME: implement
525     return false;
526 }
527
528 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
529 {
530     return false;
531 }
532
533 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
534 {
535     return false;
536 }
537
538 void AccessibilityUIElement::increment()
539 {
540 }
541
542 void AccessibilityUIElement::decrement()
543 {
544 }
545
546 void AccessibilityUIElement::showMenu()
547 {
548     ASSERT(hasPopup());
549     m_element->accDoDefaultAction(self());
550 }
551
552 void AccessibilityUIElement::press()
553 {
554     // FIXME: implement
555 }
556
557 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
558 {
559     return 0;
560 }
561
562 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
563 {
564     return 0;
565 }
566
567 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
568 {
569     return 0;
570 }
571
572 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
573 {
574     return 0;
575 }
576
577 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
578 {
579     return 0;
580 }
581
582 JSStringRef AccessibilityUIElement::accessibilityValue() const
583 {
584     BSTR valueBSTR;
585     if (FAILED(m_element->get_accValue(self(), &valueBSTR)) || !valueBSTR)
586         return JSStringCreateWithCharacters(0, 0);
587
588     wstring value(valueBSTR, SysStringLen(valueBSTR));
589     ::SysFreeString(valueBSTR);
590
591     return JSStringCreateWithCharacters(value.data(), value.length());
592 }
593
594
595 JSStringRef AccessibilityUIElement::documentEncoding()
596 {
597     return JSStringCreateWithCharacters(0, 0);
598 }
599
600 JSStringRef AccessibilityUIElement::documentURI()
601 {
602     return JSStringCreateWithCharacters(0, 0);
603 }
604
605 JSStringRef AccessibilityUIElement::url()
606 {
607     // FIXME: implement
608     return JSStringCreateWithCharacters(0, 0);
609 }
610
611 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
612 {
613     if (!functionCallback)
614         return false;
615
616     sharedFrameLoadDelegate->accessibilityController()->addNotificationListener(m_element, functionCallback);
617     return true;
618 }
619
620 void AccessibilityUIElement::removeNotificationListener()
621 {
622     // FIXME: implement
623 }
624
625 bool AccessibilityUIElement::isFocusable() const
626 {
627     // FIXME: implement
628     return false;
629 }
630
631 bool AccessibilityUIElement::isSelectable() const
632 {
633     DWORD state = accessibilityState(m_element);
634     return (state & STATE_SYSTEM_SELECTABLE) == STATE_SYSTEM_SELECTABLE;
635 }
636
637 bool AccessibilityUIElement::isMultiSelectable() const
638 {
639     DWORD multiSelectable = STATE_SYSTEM_EXTSELECTABLE | STATE_SYSTEM_MULTISELECTABLE;
640     DWORD state = accessibilityState(m_element);
641     return (state & multiSelectable) == multiSelectable;
642 }
643
644 bool AccessibilityUIElement::isSelectedOptionActive() const
645 {
646     // FIXME: implement
647     return false;
648 }
649
650 bool AccessibilityUIElement::isVisible() const
651 {
652     DWORD state = accessibilityState(m_element);
653     return (state & STATE_SYSTEM_INVISIBLE) != STATE_SYSTEM_INVISIBLE;
654 }
655
656 bool AccessibilityUIElement::isOffScreen() const
657 {
658     DWORD state = accessibilityState(m_element);
659     return (state & STATE_SYSTEM_OFFSCREEN) == STATE_SYSTEM_OFFSCREEN;
660 }
661
662 bool AccessibilityUIElement::isCollapsed() const
663 {
664     DWORD state = accessibilityState(m_element);
665     return (state & STATE_SYSTEM_COLLAPSED) == STATE_SYSTEM_COLLAPSED;
666 }
667
668 bool AccessibilityUIElement::isIgnored() const
669 {
670     // FIXME: implement
671     return false;
672 }
673
674 bool AccessibilityUIElement::hasPopup() const
675 {
676     DWORD state = accessibilityState(m_element);
677     return (state & STATE_SYSTEM_HASPOPUP) == STATE_SYSTEM_HASPOPUP;
678 }
679
680 void AccessibilityUIElement::takeFocus()
681 {
682     m_element->accSelect(SELFLAG_TAKEFOCUS, self());
683 }
684
685 void AccessibilityUIElement::takeSelection()
686 {
687     m_element->accSelect(SELFLAG_TAKESELECTION, self());
688 }
689
690 void AccessibilityUIElement::addSelection()
691 {
692     m_element->accSelect(SELFLAG_ADDSELECTION, self());
693 }
694
695 void AccessibilityUIElement::removeSelection()
696 {
697     m_element->accSelect(SELFLAG_REMOVESELECTION, self());
698 }