2 * Copyright (C) 2008, 2013, 2014 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>
33 #include <JavaScriptCore/JSStringRefBSTR.h>
34 #include <wtf/text/WTFString.h>
41 static COMPtr<IAccessibleComparable> comparableObject(IAccessible* accessible)
43 COMPtr<IServiceProvider> serviceProvider(Query, accessible);
46 COMPtr<IAccessibleComparable> comparable;
47 serviceProvider->QueryService(SID_AccessibleComparable, __uuidof(IAccessibleComparable), reinterpret_cast<void**>(&comparable));
51 AccessibilityUIElement::AccessibilityUIElement(PlatformUIElement element)
56 AccessibilityUIElement::AccessibilityUIElement(const AccessibilityUIElement& other)
57 : m_element(other.m_element)
61 AccessibilityUIElement::~AccessibilityUIElement()
65 bool AccessibilityUIElement::isEqual(AccessibilityUIElement* otherElement)
67 COMPtr<IAccessibleComparable> comparable = comparableObject(m_element.get());
68 COMPtr<IAccessibleComparable> otherComparable = comparableObject(otherElement->m_element.get());
69 if (!comparable || !otherComparable)
72 if (FAILED(comparable->isSameObject(otherComparable.get(), &isSame)))
77 void AccessibilityUIElement::getLinkedUIElements(Vector<AccessibilityUIElement>&)
81 void AccessibilityUIElement::getDocumentLinks(Vector<AccessibilityUIElement>&)
85 void AccessibilityUIElement::getChildren(Vector<AccessibilityUIElement>& children)
91 if (FAILED(m_element->get_accChildCount(&childCount)))
93 for (long i = 0; i < childCount; ++i)
94 children.append(getChildAtIndex(i));
97 void AccessibilityUIElement::getChildrenWithRange(Vector<AccessibilityUIElement>& elementVector, unsigned location, unsigned length)
103 unsigned appendedCount = 0;
104 if (FAILED(m_element->get_accChildCount(&childCount)))
106 for (long i = location; i < childCount && appendedCount < length; ++i, ++appendedCount)
107 elementVector.append(getChildAtIndex(i));
110 int AccessibilityUIElement::childrenCount()
116 m_element->get_accChildCount(&childCount);
120 int AccessibilityUIElement::rowCount()
126 int AccessibilityUIElement::columnCount()
132 AccessibilityUIElement AccessibilityUIElement::elementAtPoint(int x, int y)
137 AccessibilityUIElement AccessibilityUIElement::linkedUIElementAtIndex(unsigned index)
143 AccessibilityUIElement AccessibilityUIElement::getChildAtIndex(unsigned index)
148 COMPtr<IDispatch> child;
150 ::VariantInit(&vChild);
151 V_VT(&vChild) = VT_I4;
152 // In MSAA, index 0 is the object itself.
153 V_I4(&vChild) = index + 1;
154 if (FAILED(m_element->get_accChild(vChild, &child)))
156 return COMPtr<IAccessible>(Query, child);
159 unsigned AccessibilityUIElement::indexOfChild(AccessibilityUIElement* element)
165 JSStringRef AccessibilityUIElement::allAttributes()
167 return JSStringCreateWithCharacters(0, 0);
170 JSStringRef AccessibilityUIElement::attributesOfLinkedUIElements()
172 return JSStringCreateWithCharacters(0, 0);
175 JSStringRef AccessibilityUIElement::attributesOfDocumentLinks()
177 return JSStringCreateWithCharacters(0, 0);
180 AccessibilityUIElement AccessibilityUIElement::titleUIElement()
182 COMPtr<IAccessible> platformElement = platformUIElement();
184 COMPtr<IAccessibleComparable> comparable = comparableObject(platformElement.get());
189 ::VariantInit(&value);
191 _bstr_t titleUIElementAttributeKey(L"AXTitleUIElementAttribute");
192 if (FAILED(comparable->get_attribute(titleUIElementAttributeKey, &value))) {
193 ::VariantClear(&value);
197 if (V_VT(&value) == VT_EMPTY) {
198 ::VariantClear(&value);
202 ASSERT(V_VT(&value) == VT_UNKNOWN);
204 if (V_VT(&value) != VT_UNKNOWN) {
205 ::VariantClear(&value);
209 COMPtr<IAccessible> titleElement(Query, value.punkVal);
211 value.punkVal->Release();
212 ::VariantClear(&value);
217 AccessibilityUIElement AccessibilityUIElement::parentElement()
222 COMPtr<IDispatch> parent;
223 m_element->get_accParent(&parent);
225 COMPtr<IAccessible> parentAccessible(Query, parent);
226 return parentAccessible;
229 JSStringRef AccessibilityUIElement::attributesOfChildren()
231 return JSStringCreateWithCharacters(0, 0);
234 JSStringRef AccessibilityUIElement::parameterizedAttributeNames()
236 return JSStringCreateWithCharacters(0, 0);
239 static VARIANT& self()
241 static VARIANT vSelf;
242 static bool haveInitialized;
244 if (!haveInitialized) {
245 ::VariantInit(&vSelf);
246 V_VT(&vSelf) = VT_I4;
247 V_I4(&vSelf) = CHILDID_SELF;
252 JSStringRef AccessibilityUIElement::role()
255 return JSStringCreateWithCharacters(0, 0);
258 if (FAILED(m_element->get_accRole(self(), &vRole)))
259 return JSStringCreateWithCharacters(0, 0);
261 ASSERT(V_VT(&vRole) == VT_I4 || V_VT(&vRole) == VT_BSTR);
264 if (V_VT(&vRole) == VT_I4) {
265 unsigned roleTextLength = ::GetRoleText(V_I4(&vRole), 0, 0) + 1;
267 Vector<TCHAR> roleText(roleTextLength);
269 ::GetRoleText(V_I4(&vRole), roleText.data(), roleTextLength);
271 result = roleText.data();
272 } else if (V_VT(&vRole) == VT_BSTR)
273 result = wstring(V_BSTR(&vRole), ::SysStringLen(V_BSTR(&vRole)));
275 ::VariantClear(&vRole);
277 return JSStringCreateWithCharacters(result.data(), result.length());
280 JSStringRef AccessibilityUIElement::subrole()
285 JSStringRef AccessibilityUIElement::roleDescription()
290 JSStringRef AccessibilityUIElement::computedRoleString()
295 JSStringRef AccessibilityUIElement::title()
298 return JSStringCreateWithCharacters(0, 0);
301 if (FAILED(m_element->get_accName(self(), &titleBSTR.GetBSTR())) || !titleBSTR.length())
302 return JSStringCreateWithCharacters(0, 0);
304 return JSStringCreateWithBSTR(titleBSTR);
307 JSStringRef AccessibilityUIElement::description()
310 return JSStringCreateWithCharacters(0, 0);
312 _bstr_t descriptionBSTR;
313 if (FAILED(m_element->get_accDescription(self(), &descriptionBSTR.GetBSTR())) || !descriptionBSTR.length())
314 return JSStringCreateWithCharacters(0, 0);
315 return JSStringCreateWithBSTR(descriptionBSTR);
318 JSStringRef AccessibilityUIElement::stringValue()
320 return JSStringCreateWithCharacters(0, 0);
323 JSStringRef AccessibilityUIElement::language()
325 return JSStringCreateWithCharacters(0, 0);
328 JSStringRef AccessibilityUIElement::helpText() const
331 return JSStringCreateWithCharacters(0, 0);
333 _bstr_t helpTextBSTR;
334 if (FAILED(m_element->get_accHelp(self(), &helpTextBSTR.GetBSTR())) || !helpTextBSTR.length())
335 return JSStringCreateWithCharacters(0, 0);
336 return JSStringCreateWithBSTR(helpTextBSTR);
339 double AccessibilityUIElement::x()
344 long x, y, width, height;
345 if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
350 double AccessibilityUIElement::y()
355 long x, y, width, height;
356 if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
361 double AccessibilityUIElement::width()
366 long x, y, width, height;
367 if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
372 double AccessibilityUIElement::height()
377 long x, y, width, height;
378 if (FAILED(m_element->accLocation(&x, &y, &width, &height, self())))
383 double AccessibilityUIElement::clickPointX()
388 double AccessibilityUIElement::clickPointY()
393 JSStringRef AccessibilityUIElement::valueDescription()
398 static DWORD accessibilityState(COMPtr<IAccessible> element)
401 element->get_accState(self(), &state);
403 ASSERT(V_VT(&state) == VT_I4);
405 DWORD result = state.lVal;
406 VariantClear(&state);
411 bool AccessibilityUIElement::isFocused() const
417 bool AccessibilityUIElement::isSelected() const
419 DWORD state = accessibilityState(m_element);
420 return (state & STATE_SYSTEM_SELECTED) == STATE_SYSTEM_SELECTED;
423 int AccessibilityUIElement::hierarchicalLevel() const
428 bool AccessibilityUIElement::ariaIsGrabbed() const
433 JSStringRef AccessibilityUIElement::ariaDropEffects() const
438 bool AccessibilityUIElement::isExpanded() const
443 bool AccessibilityUIElement::isChecked() const
449 if (FAILED(m_element->get_accState(self(), &vState)))
452 return vState.lVal & STATE_SYSTEM_CHECKED;
455 bool AccessibilityUIElement::isIndeterminate() const
461 JSStringRef AccessibilityUIElement::orientation() const
466 double AccessibilityUIElement::intValue() const
472 if (FAILED(m_element->get_accValue(self(), &valueBSTR.GetBSTR())) || !valueBSTR.length())
476 return _tcstod(static_cast<TCHAR*>(valueBSTR), &ignored);
479 double AccessibilityUIElement::minValue()
484 double AccessibilityUIElement::maxValue()
489 bool AccessibilityUIElement::isPressActionSupported()
495 if (FAILED(m_element->get_accDefaultAction(self(), &valueBSTR.GetBSTR())))
498 if (!valueBSTR.length())
504 bool AccessibilityUIElement::isIncrementActionSupported()
509 bool AccessibilityUIElement::isDecrementActionSupported()
514 bool AccessibilityUIElement::isEnabled()
516 DWORD state = accessibilityState(m_element);
517 return (state & STATE_SYSTEM_UNAVAILABLE) != STATE_SYSTEM_UNAVAILABLE;
520 bool AccessibilityUIElement::isRequired() const
526 int AccessibilityUIElement::insertionPointLineNumber()
531 JSStringRef AccessibilityUIElement::attributesOfColumnHeaders()
533 return JSStringCreateWithCharacters(0, 0);
536 JSStringRef AccessibilityUIElement::attributesOfRowHeaders()
538 return JSStringCreateWithCharacters(0, 0);
541 JSStringRef AccessibilityUIElement::attributesOfColumns()
543 return JSStringCreateWithCharacters(0, 0);
546 JSStringRef AccessibilityUIElement::attributesOfRows()
548 return JSStringCreateWithCharacters(0, 0);
551 JSStringRef AccessibilityUIElement::attributesOfVisibleCells()
553 return JSStringCreateWithCharacters(0, 0);
556 JSStringRef AccessibilityUIElement::attributesOfHeader()
558 return JSStringCreateWithCharacters(0, 0);
561 int AccessibilityUIElement::indexInTable()
566 JSStringRef AccessibilityUIElement::rowIndexRange()
568 return JSStringCreateWithCharacters(0, 0);
571 JSStringRef AccessibilityUIElement::columnIndexRange()
573 return JSStringCreateWithCharacters(0, 0);
576 int AccessibilityUIElement::lineForIndex(int)
581 JSStringRef AccessibilityUIElement::boundsForRange(unsigned location, unsigned length)
583 return JSStringCreateWithCharacters(0, 0);
586 JSStringRef AccessibilityUIElement::stringForRange(unsigned, unsigned)
588 return JSStringCreateWithCharacters(0, 0);
591 JSStringRef AccessibilityUIElement::attributedStringForRange(unsigned, unsigned)
593 return JSStringCreateWithCharacters(0, 0);
596 bool AccessibilityUIElement::attributedStringRangeIsMisspelled(unsigned, unsigned)
601 unsigned AccessibilityUIElement::uiElementCountForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
606 AccessibilityUIElement AccessibilityUIElement::uiElementForSearchPredicate(JSContextRef context, AccessibilityUIElement* startElement, bool isDirectionNext, JSValueRef searchKey, JSStringRef searchText, bool visibleOnly, bool immediateDescendantsOnly)
611 JSStringRef AccessibilityUIElement::selectTextWithCriteria(JSContextRef context, JSStringRef ambiguityResolution, JSValueRef searchStrings, JSStringRef replacementString)
616 AccessibilityUIElement AccessibilityUIElement::cellForColumnAndRow(unsigned column, unsigned row)
621 JSStringRef AccessibilityUIElement::selectedTextRange()
623 return JSStringCreateWithCharacters(0, 0);
626 void AccessibilityUIElement::setSelectedTextRange(unsigned location, unsigned length)
630 JSStringRef AccessibilityUIElement::stringAttributeValue(JSStringRef attribute)
633 return JSStringCreateWithCharacters(0, 0);
636 double AccessibilityUIElement::numberAttributeValue(JSStringRef attribute)
642 bool AccessibilityUIElement::boolAttributeValue(JSStringRef attribute)
648 bool AccessibilityUIElement::isAttributeSettable(JSStringRef attribute)
653 bool AccessibilityUIElement::isAttributeSupported(JSStringRef attribute)
658 void AccessibilityUIElement::increment()
662 void AccessibilityUIElement::decrement()
666 void AccessibilityUIElement::showMenu()
672 m_element->accDoDefaultAction(self());
675 void AccessibilityUIElement::press()
680 m_element->accDoDefaultAction(self());
683 AccessibilityUIElement AccessibilityUIElement::disclosedRowAtIndex(unsigned index)
688 AccessibilityUIElement AccessibilityUIElement::ariaOwnsElementAtIndex(unsigned index)
693 AccessibilityUIElement AccessibilityUIElement::ariaFlowToElementAtIndex(unsigned index)
698 AccessibilityUIElement AccessibilityUIElement::ariaControlsElementAtIndex(unsigned index)
703 AccessibilityUIElement AccessibilityUIElement::selectedRowAtIndex(unsigned index)
708 AccessibilityUIElement AccessibilityUIElement::rowAtIndex(unsigned index)
713 AccessibilityUIElement AccessibilityUIElement::disclosedByRow()
718 JSStringRef AccessibilityUIElement::accessibilityValue() const
721 return JSStringCreateWithCharacters(0, 0);
724 if (FAILED(m_element->get_accValue(self(), &valueBSTR.GetBSTR())) || !valueBSTR.length())
725 return JSStringCreateWithCharacters(0, 0);
727 return JSStringCreateWithBSTR(valueBSTR);
731 JSStringRef AccessibilityUIElement::documentEncoding()
733 return JSStringCreateWithCharacters(0, 0);
736 JSStringRef AccessibilityUIElement::documentURI()
738 return JSStringCreateWithCharacters(0, 0);
741 JSStringRef AccessibilityUIElement::url()
744 return JSStringCreateWithCharacters(0, 0);
747 bool AccessibilityUIElement::addNotificationListener(JSObjectRef functionCallback)
749 if (!functionCallback)
752 sharedFrameLoadDelegate->accessibilityController()->winAddNotificationListener(m_element, functionCallback);
756 void AccessibilityUIElement::removeNotificationListener()
761 bool AccessibilityUIElement::isFocusable() const
767 bool AccessibilityUIElement::isSelectable() const
769 DWORD state = accessibilityState(m_element);
770 return (state & STATE_SYSTEM_SELECTABLE) == STATE_SYSTEM_SELECTABLE;
773 bool AccessibilityUIElement::isMultiSelectable() const
775 DWORD multiSelectable = STATE_SYSTEM_EXTSELECTABLE | STATE_SYSTEM_MULTISELECTABLE;
776 DWORD state = accessibilityState(m_element);
777 return (state & multiSelectable) == multiSelectable;
780 bool AccessibilityUIElement::isSelectedOptionActive() const
786 bool AccessibilityUIElement::isVisible() const
788 DWORD state = accessibilityState(m_element);
789 return (state & STATE_SYSTEM_INVISIBLE) != STATE_SYSTEM_INVISIBLE;
792 bool AccessibilityUIElement::isOffScreen() const
794 DWORD state = accessibilityState(m_element);
795 return (state & STATE_SYSTEM_OFFSCREEN) == STATE_SYSTEM_OFFSCREEN;
798 bool AccessibilityUIElement::isCollapsed() const
800 DWORD state = accessibilityState(m_element);
801 return (state & STATE_SYSTEM_COLLAPSED) == STATE_SYSTEM_COLLAPSED;
804 bool AccessibilityUIElement::isIgnored() const
810 bool AccessibilityUIElement::hasPopup() const
812 DWORD state = accessibilityState(m_element);
813 return (state & STATE_SYSTEM_HASPOPUP) == STATE_SYSTEM_HASPOPUP;
816 void AccessibilityUIElement::takeFocus()
821 m_element->accSelect(SELFLAG_TAKEFOCUS, self());
824 void AccessibilityUIElement::takeSelection()
829 m_element->accSelect(SELFLAG_TAKESELECTION, self());
832 void AccessibilityUIElement::addSelection()
837 m_element->accSelect(SELFLAG_ADDSELECTION, self());
840 void AccessibilityUIElement::removeSelection()
845 m_element->accSelect(SELFLAG_REMOVESELECTION, self());
848 void AccessibilityUIElement::scrollToMakeVisible()
853 void AccessibilityUIElement::scrollToMakeVisibleWithSubFocus(int x, int y, int width, int height)
858 void AccessibilityUIElement::scrollToGlobalPoint(int x, int y)
863 JSStringRef AccessibilityUIElement::classList() const
869 unsigned AccessibilityUIElement::selectedChildrenCount() const
875 AccessibilityUIElement AccessibilityUIElement::selectedChildAtIndex(unsigned) const
881 void AccessibilityUIElement::columnHeaders(Vector<AccessibilityUIElement>&) const
886 void AccessibilityUIElement::rowHeaders(Vector<AccessibilityUIElement>&) const