2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "AccessibilityUIElement.h"
29 #include "AccessibilityController.h"
30 #include "DumpRenderTree.h"
31 #include "FrameLoadDelegate.h"
32 #include <JavaScriptCore/JSStringRef.h>
38 static COMPtr<IAccessibleComparable> comparableObject(IAccessible* accessible)
40 COMPtr<IServiceProvider> serviceProvider(Query, accessible);
43 COMPtr<IAccessibleComparable> comparable;
44 serviceProvider->QueryService(SID_AccessibleComparable, __uuidof(IAccessibleComparable), reinterpret_cast<void**>(&comparable));
48 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
53 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
54 : m_element(other.m_element)
58 AccessibilityUIElement::~AccessibilityUIElement()
62 bool AccessibilityUIElement::isEqual(AccessibilityUIElement* otherElement)
64 COMPtr<IAccessibleComparable> comparable = comparableObject(m_element.get());
65 COMPtr<IAccessibleComparable> otherComparable = comparableObject(otherElement->m_element.get());
66 if (!comparable || !otherComparable)
69 if (FAILED(comparable->isSameObject(otherComparable.get(), &isSame)))
74 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>&)
78 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
82 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
85 if (FAILED(m_element->get_accChildCount(&childCount)))
87 for (long i = 0; i < childCount; ++i)
88 children.append(getChildAtIndex(i));
91 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
94 unsigned appendedCount = 0;
95 if (FAILED(m_element->get_accChildCount(&childCount)))
97 for (long i = location; i < childCount && appendedCount < length; ++i, ++appendedCount)
98 elementVector.append(getChildAtIndex(i));
101 int AccessibilityUIElement::childrenCount()
104 m_element->get_accChildCount(&childCount);
108 int AccessibilityUIElement::rowCount()
114 int AccessibilityUIElement::columnCount()
120 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
125 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
131 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
133 COMPtr<IDispatch> child;
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)))
141 return COMPtr<IAccessible>(Query, child);
144 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
150 JSStringRef AccessibilityUIElement::allAttributes()
152 return JSStringCreateWithCharacters(0, 0);
155 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
157 return JSStringCreateWithCharacters(0, 0);
160 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
162 return JSStringCreateWithCharacters(0, 0);
165 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
170 AccessibilityUIElement AccessibilityUIElement::parentElement()
172 COMPtr<IDispatch> parent;
173 m_element->get_accParent(&parent);
175 COMPtr<IAccessible> parentAccessible(Query, parent);
176 return parentAccessible;
179 JSStringRef AccessibilityUIElement::attributesOfChildren()
181 return JSStringCreateWithCharacters(0, 0);
184 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
186 return JSStringCreateWithCharacters(0, 0);
189 static VARIANT& self()
191 static VARIANT vSelf;
192 static bool haveInitialized;
194 if (!haveInitialized) {
195 ::VariantInit(&vSelf);
196 V_VT(&vSelf) = VT_I4;
197 V_I4(&vSelf) = CHILDID_SELF;
202 JSStringRef AccessibilityUIElement::role()
205 if (FAILED(m_element->get_accRole(self(), &vRole)))
206 return JSStringCreateWithCharacters(0, 0);
208 ASSERT(V_VT(&vRole) == VT_I4 || V_VT(&vRole) == VT_BSTR);
211 if (V_VT(&vRole) == VT_I4) {
212 unsigned roleTextLength = ::GetRoleText(V_I4(&vRole), 0, 0) + 1;
214 Vector<TCHAR> roleText(roleTextLength);
216 ::GetRoleText(V_I4(&vRole), roleText.data(), roleTextLength);
218 result = roleText.data();
219 } else if (V_VT(&vRole) == VT_BSTR)
220 result = wstring(V_BSTR(&vRole), ::SysStringLen(V_BSTR(&vRole)));
222 ::VariantClear(&vRole);
224 return JSStringCreateWithCharacters(result.data(), result.length());
227 JSStringRef AccessibilityUIElement::subrole()
232 JSStringRef AccessibilityUIElement::roleDescription()
237 JSStringRef AccessibilityUIElement::title()
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());
247 JSStringRef AccessibilityUIElement::description()
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());
257 JSStringRef AccessibilityUIElement::stringValue()
259 return JSStringCreateWithCharacters(0, 0);
262 JSStringRef AccessibilityUIElement::language()
264 return JSStringCreateWithCharacters(0, 0);
267 JSStringRef AccessibilityUIElement::helpText() const
272 double AccessibilityUIElement::x()
274 long x, y, width, height;
275 if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
280 double AccessibilityUIElement::y()
282 long x, y, width, height;
283 if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
288 double AccessibilityUIElement::width()
290 long x, y, width, height;
291 if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
296 double AccessibilityUIElement::height()
298 long x, y, width, height;
299 if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
304 double AccessibilityUIElement::clickPointX()
309 double AccessibilityUIElement::clickPointY()
314 JSStringRef AccessibilityUIElement::valueDescription()
319 static DWORD accessibilityState(COMPtr<IAccessible> element)
322 element->get_accState(self(), &state);
324 ASSERT(V_VT(&state) == VT_I4);
326 DWORD result = state.lVal;
327 VariantClear(&state);
332 bool AccessibilityUIElement::isFocused() const
338 bool AccessibilityUIElement::isSelected() const
340 DWORD state = accessibilityState(m_element);
341 return (state & STATE_SYSTEM_SELECTED) == STATE_SYSTEM_SELECTED;
344 int AccessibilityUIElement::hierarchicalLevel() const
349 bool AccessibilityUIElement::ariaIsGrabbed() const
354 JSStringRef AccessibilityUIElement::ariaDropEffects() const
359 bool AccessibilityUIElement::isExpanded() const
364 bool AccessibilityUIElement::isChecked() const
367 if (FAILED(m_element->get_accState(self(), &vState)))
370 return vState.lVal & STATE_SYSTEM_CHECKED;
373 JSStringRef AccessibilityUIElement::orientation() const
378 double AccessibilityUIElement::intValue() const
381 if (FAILED(m_element->get_accValue(self(), &valueBSTR)) || !valueBSTR)
383 wstring value(valueBSTR, SysStringLen(valueBSTR));
384 ::SysFreeString(valueBSTR);
386 return _tcstod(value.data(), &ignored);
389 double AccessibilityUIElement::minValue()
394 double AccessibilityUIElement::maxValue()
399 bool AccessibilityUIElement::isActionSupported(JSStringRef action)
404 bool AccessibilityUIElement::isEnabled()
406 DWORD state = accessibilityState(m_element);
407 return (state & STATE_SYSTEM_UNAVAILABLE) != STATE_SYSTEM_UNAVAILABLE;
410 bool AccessibilityUIElement::isRequired() const
416 int AccessibilityUIElement::insertionPointLineNumber()
421 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
423 return JSStringCreateWithCharacters(0, 0);
426 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
428 return JSStringCreateWithCharacters(0, 0);
431 JSStringRef AccessibilityUIElement::attributesOfColumns()
433 return JSStringCreateWithCharacters(0, 0);
436 JSStringRef AccessibilityUIElement::attributesOfRows()
438 return JSStringCreateWithCharacters(0, 0);
441 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
443 return JSStringCreateWithCharacters(0, 0);
446 JSStringRef AccessibilityUIElement::attributesOfHeader()
448 return JSStringCreateWithCharacters(0, 0);
451 int AccessibilityUIElement::indexInTable()
456 JSStringRef AccessibilityUIElement::rowIndexRange()
458 return JSStringCreateWithCharacters(0, 0);
461 JSStringRef AccessibilityUIElement::columnIndexRange()
463 return JSStringCreateWithCharacters(0, 0);
466 int AccessibilityUIElement::lineForIndex(int)
471 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
473 return JSStringCreateWithCharacters(0, 0);
476 JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned)
478 return JSStringCreateWithCharacters(0, 0);
481 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
483 return JSStringCreateWithCharacters(0, 0);
486 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned, unsigned)
491 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(AccessibilityUIElement* startElement, bool isDirectionNext, JSStringRef searchKey, JSStringRef searchText)
496 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
501 JSStringRef AccessibilityUIElement::selectedTextRange()
503 return JSStringCreateWithCharacters(0, 0);
506 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
510 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
513 return JSStringCreateWithCharacters(0, 0);
516 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
522 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
528 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
533 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
538 void AccessibilityUIElement::increment()
542 void AccessibilityUIElement::decrement()
546 void AccessibilityUIElement::showMenu()
549 m_element->accDoDefaultAction(self());
552 void AccessibilityUIElement::press()
557 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
562 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
567 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
572 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
577 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
582 JSStringRef AccessibilityUIElement::accessibilityValue() const
585 if (FAILED(m_element->get_accValue(self(), &valueBSTR)) || !valueBSTR)
586 return JSStringCreateWithCharacters(0, 0);
588 wstring value(valueBSTR, SysStringLen(valueBSTR));
589 ::SysFreeString(valueBSTR);
591 return JSStringCreateWithCharacters(value.data(), value.length());
595 JSStringRef AccessibilityUIElement::documentEncoding()
597 return JSStringCreateWithCharacters(0, 0);
600 JSStringRef AccessibilityUIElement::documentURI()
602 return JSStringCreateWithCharacters(0, 0);
605 JSStringRef AccessibilityUIElement::url()
608 return JSStringCreateWithCharacters(0, 0);
611 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
613 if (!functionCallback)
616 sharedFrameLoadDelegate->accessibilityController()->addNotificationListener(m_element, functionCallback);
620 void AccessibilityUIElement::removeNotificationListener()
625 bool AccessibilityUIElement::isFocusable() const
631 bool AccessibilityUIElement::isSelectable() const
633 DWORD state = accessibilityState(m_element);
634 return (state & STATE_SYSTEM_SELECTABLE) == STATE_SYSTEM_SELECTABLE;
637 bool AccessibilityUIElement::isMultiSelectable() const
639 DWORD multiSelectable = STATE_SYSTEM_EXTSELECTABLE | STATE_SYSTEM_MULTISELECTABLE;
640 DWORD state = accessibilityState(m_element);
641 return (state & multiSelectable) == multiSelectable;
644 bool AccessibilityUIElement::isSelectedOptionActive() const
650 bool AccessibilityUIElement::isVisible() const
652 DWORD state = accessibilityState(m_element);
653 return (state & STATE_SYSTEM_INVISIBLE) != STATE_SYSTEM_INVISIBLE;
656 bool AccessibilityUIElement::isOffScreen() const
658 DWORD state = accessibilityState(m_element);
659 return (state & STATE_SYSTEM_OFFSCREEN) == STATE_SYSTEM_OFFSCREEN;
662 bool AccessibilityUIElement::isCollapsed() const
664 DWORD state = accessibilityState(m_element);
665 return (state & STATE_SYSTEM_COLLAPSED) == STATE_SYSTEM_COLLAPSED;
668 bool AccessibilityUIElement::isIgnored() const
674 bool AccessibilityUIElement::hasPopup() const
676 DWORD state = accessibilityState(m_element);
677 return (state & STATE_SYSTEM_HASPOPUP) == STATE_SYSTEM_HASPOPUP;
680 void AccessibilityUIElement::takeFocus()
682 m_element->accSelect(SELFLAG_TAKEFOCUS, self());
685 void AccessibilityUIElement::takeSelection()
687 m_element->accSelect(SELFLAG_TAKESELECTION, self());
690 void AccessibilityUIElement::addSelection()
692 m_element->accSelect(SELFLAG_ADDSELECTION, self());
695 void AccessibilityUIElement::removeSelection()
697 m_element->accSelect(SELFLAG_REMOVESELECTION, self());