1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "AccAttributes.h"
8 #include "nsAccUtils.h"
9 #include "nsComponentManagerUtils.h"
10 #include "nsIAccessibleRelation.h"
11 #include "nsIAccessibleRole.h"
12 #include "nsAccessibleRelation.h"
14 #include "RootAccessible.h"
15 #include "xpcAccessibleDocument.h"
17 #include "nsIMutableArray.h"
18 #include "nsPersistentProperties.h"
20 #ifdef MOZ_WIDGET_COCOA
21 # include "xpcAccessibleMacInterface.h"
24 using namespace mozilla::a11y
;
27 xpcAccessible::GetParent(nsIAccessible
** aParent
) {
28 NS_ENSURE_ARG_POINTER(aParent
);
30 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
32 Accessible
* parent
= IntlGeneric()->Parent();
33 NS_IF_ADDREF(*aParent
= ToXPC(parent
));
38 xpcAccessible::GetNextSibling(nsIAccessible
** aNextSibling
) {
39 NS_ENSURE_ARG_POINTER(aNextSibling
);
40 *aNextSibling
= nullptr;
41 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
43 NS_IF_ADDREF(*aNextSibling
= ToXPC(IntlGeneric()->NextSibling()));
49 xpcAccessible::GetPreviousSibling(nsIAccessible
** aPreviousSibling
) {
50 NS_ENSURE_ARG_POINTER(aPreviousSibling
);
51 *aPreviousSibling
= nullptr;
52 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
54 NS_IF_ADDREF(*aPreviousSibling
= ToXPC(IntlGeneric()->PrevSibling()));
60 xpcAccessible::GetFirstChild(nsIAccessible
** aFirstChild
) {
61 NS_ENSURE_ARG_POINTER(aFirstChild
);
62 *aFirstChild
= nullptr;
64 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
66 NS_IF_ADDREF(*aFirstChild
= ToXPC(IntlGeneric()->FirstChild()));
71 xpcAccessible::GetLastChild(nsIAccessible
** aLastChild
) {
72 NS_ENSURE_ARG_POINTER(aLastChild
);
73 *aLastChild
= nullptr;
75 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
77 NS_IF_ADDREF(*aLastChild
= ToXPC(IntlGeneric()->LastChild()));
82 xpcAccessible::GetChildCount(int32_t* aChildCount
) {
83 NS_ENSURE_ARG_POINTER(aChildCount
);
85 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
87 *aChildCount
= IntlGeneric()->ChildCount();
92 xpcAccessible::GetChildAt(int32_t aChildIndex
, nsIAccessible
** aChild
) {
93 NS_ENSURE_ARG_POINTER(aChild
);
96 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
98 // If child index is negative, then return last child.
99 // XXX: do we really need this?
100 if (aChildIndex
< 0) aChildIndex
= IntlGeneric()->ChildCount() - 1;
102 Accessible
* child
= IntlGeneric()->ChildAt(aChildIndex
);
103 if (!child
) return NS_ERROR_INVALID_ARG
;
105 NS_ADDREF(*aChild
= ToXPC(child
));
110 xpcAccessible::GetChildren(nsIArray
** aChildren
) {
111 NS_ENSURE_ARG_POINTER(aChildren
);
112 *aChildren
= nullptr;
114 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
117 nsCOMPtr
<nsIMutableArray
> children
=
118 do_CreateInstance(NS_ARRAY_CONTRACTID
, &rv
);
119 NS_ENSURE_SUCCESS(rv
, rv
);
121 uint32_t childCount
= IntlGeneric()->ChildCount();
122 for (uint32_t childIdx
= 0; childIdx
< childCount
; childIdx
++) {
123 Accessible
* child
= IntlGeneric()->ChildAt(childIdx
);
124 children
->AppendElement(static_cast<nsIAccessible
*>(ToXPC(child
)));
127 children
.forget(aChildren
);
132 xpcAccessible::GetIndexInParent(int32_t* aIndexInParent
) {
133 NS_ENSURE_ARG_POINTER(aIndexInParent
);
134 *aIndexInParent
= -1;
135 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
137 *aIndexInParent
= IntlGeneric()->IndexInParent();
139 return *aIndexInParent
!= -1 ? NS_OK
: NS_ERROR_FAILURE
;
143 xpcAccessible::GetUniqueID(int64_t* aUniqueID
) {
144 NS_ENSURE_ARG_POINTER(aUniqueID
);
146 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
148 if (IntlGeneric()->IsLocal()) {
149 *aUniqueID
= reinterpret_cast<uintptr_t>(Intl()->UniqueID());
150 } else if (IntlGeneric()->IsRemote()) {
151 *aUniqueID
= IntlGeneric()->AsRemote()->ID();
158 xpcAccessible::GetDOMNode(nsINode
** aDOMNode
) {
159 NS_ENSURE_ARG_POINTER(aDOMNode
);
162 if (!Intl()) return NS_ERROR_FAILURE
;
164 nsCOMPtr
<nsINode
> node
= Intl()->GetNode();
165 node
.forget(aDOMNode
);
171 xpcAccessible::GetId(nsAString
& aID
) {
172 if (!IntlGeneric()) {
173 return NS_ERROR_FAILURE
;
176 RemoteAccessible
* proxy
= IntlGeneric()->AsRemote();
178 return NS_ERROR_FAILURE
;
182 proxy
->DOMNodeID(id
);
189 xpcAccessible::GetDocument(nsIAccessibleDocument
** aDocument
) {
190 NS_ENSURE_ARG_POINTER(aDocument
);
191 *aDocument
= nullptr;
193 if (!Intl()) return NS_ERROR_FAILURE
;
195 NS_IF_ADDREF(*aDocument
= ToXPCDocument(Intl()->Document()));
200 xpcAccessible::GetRootDocument(nsIAccessibleDocument
** aRootDocument
) {
201 NS_ENSURE_ARG_POINTER(aRootDocument
);
202 *aRootDocument
= nullptr;
204 if (!Intl()) return NS_ERROR_FAILURE
;
206 NS_IF_ADDREF(*aRootDocument
= ToXPCDocument(Intl()->RootAccessible()));
211 xpcAccessible::GetRole(uint32_t* aRole
) {
212 NS_ENSURE_ARG_POINTER(aRole
);
213 *aRole
= nsIAccessibleRole::ROLE_NOTHING
;
215 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
217 *aRole
= IntlGeneric()->Role();
222 xpcAccessible::GetState(uint32_t* aState
, uint32_t* aExtraState
) {
223 NS_ENSURE_ARG_POINTER(aState
);
225 Accessible
* acc
= IntlGeneric();
227 nsAccUtils::To32States(acc
->State(), aState
, aExtraState
);
229 nsAccUtils::To32States(states::DEFUNCT
, aState
, aExtraState
);
236 xpcAccessible::GetName(nsAString
& aName
) {
239 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
242 IntlGeneric()->Name(name
);
250 xpcAccessible::GetDescription(nsAString
& aDescription
) {
251 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
254 IntlGeneric()->Description(desc
);
256 aDescription
.Assign(desc
);
262 xpcAccessible::GetLanguage(nsAString
& aLanguage
) {
263 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
266 IntlGeneric()->Language(lang
);
268 aLanguage
.Assign(lang
);
273 xpcAccessible::GetValue(nsAString
& aValue
) {
274 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
277 IntlGeneric()->Value(value
);
279 aValue
.Assign(value
);
285 xpcAccessible::GetAccessKey(nsAString
& aAccessKey
) {
286 aAccessKey
.Truncate();
288 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
290 IntlGeneric()->AccessKey().ToString(aAccessKey
);
295 xpcAccessible::GetKeyboardShortcut(nsAString
& aKeyBinding
) {
296 aKeyBinding
.Truncate();
297 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
299 if (IntlGeneric()->IsRemote()) {
300 return NS_ERROR_NOT_IMPLEMENTED
;
302 Intl()->KeyboardShortcut().ToString(aKeyBinding
);
307 xpcAccessible::GetAttributes(nsIPersistentProperties
** aAttributes
) {
308 NS_ENSURE_ARG_POINTER(aAttributes
);
309 *aAttributes
= nullptr;
311 if (!IntlGeneric()) {
312 return NS_ERROR_FAILURE
;
315 RefPtr
<nsPersistentProperties
> props
= new nsPersistentProperties();
317 RefPtr
<AccAttributes
> attributes
= IntlGeneric()->Attributes();
320 for (auto iter
: *attributes
) {
322 iter
.NameAsString(name
);
325 iter
.ValueAsString(value
);
327 props
->SetStringProperty(NS_ConvertUTF16toUTF8(name
), value
, unused
);
330 props
.forget(aAttributes
);
335 xpcAccessible::GetCache(nsIPersistentProperties
** aCachedFields
) {
336 NS_ENSURE_ARG_POINTER(aCachedFields
);
337 *aCachedFields
= nullptr;
339 if (!IntlGeneric()) {
340 return NS_ERROR_FAILURE
;
343 RefPtr
<nsPersistentProperties
> props
= new nsPersistentProperties();
344 if (RemoteAccessible
* remoteAcc
= IntlGeneric()->AsRemote()) {
345 if (RefPtr
<AccAttributes
> cachedFields
= remoteAcc
->mCachedFields
) {
347 for (auto iter
: *cachedFields
) {
349 iter
.NameAsString(name
);
352 iter
.ValueAsString(value
);
354 props
->SetStringProperty(NS_ConvertUTF16toUTF8(name
), value
, unused
);
359 props
.forget(aCachedFields
);
364 xpcAccessible::GetNativeInterface(nsISupports
** aNativeInterface
) {
365 #ifdef MOZ_WIDGET_COCOA
366 NS_ENSURE_ARG_POINTER(aNativeInterface
);
368 // We don't cache or store this instance anywhere so each get returns a
369 // different instance. So `acc.nativeInterface != acc.nativeInterface`. This
370 // just seems simpler and more robust for now.
371 nsCOMPtr
<nsISupports
> macIface
= static_cast<nsIAccessibleMacInterface
*>(
372 new xpcAccessibleMacInterface(IntlGeneric()));
373 macIface
.swap(*aNativeInterface
);
377 return NS_ERROR_NOT_IMPLEMENTED
;
382 xpcAccessible::GetBounds(int32_t* aX
, int32_t* aY
, int32_t* aWidth
,
384 NS_ENSURE_ARG_POINTER(aX
);
386 NS_ENSURE_ARG_POINTER(aY
);
388 NS_ENSURE_ARG_POINTER(aWidth
);
390 NS_ENSURE_ARG_POINTER(aHeight
);
393 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
395 LayoutDeviceIntRect rect
= IntlGeneric()->Bounds();
396 rect
.GetRect(aX
, aY
, aWidth
, aHeight
);
401 xpcAccessible::GetBoundsInCSSPixels(int32_t* aX
, int32_t* aY
, int32_t* aWidth
,
403 NS_ENSURE_ARG_POINTER(aX
);
405 NS_ENSURE_ARG_POINTER(aY
);
407 NS_ENSURE_ARG_POINTER(aWidth
);
409 NS_ENSURE_ARG_POINTER(aHeight
);
412 if (!IntlGeneric()) {
413 return NS_ERROR_FAILURE
;
416 nsIntRect rect
= IntlGeneric()->BoundsInCSSPixels();
417 rect
.GetRect(aX
, aY
, aWidth
, aHeight
);
422 xpcAccessible::GroupPosition(int32_t* aGroupLevel
,
423 int32_t* aSimilarItemsInGroup
,
424 int32_t* aPositionInGroup
) {
425 NS_ENSURE_ARG_POINTER(aGroupLevel
);
426 NS_ENSURE_ARG_POINTER(aSimilarItemsInGroup
);
427 NS_ENSURE_ARG_POINTER(aPositionInGroup
);
429 GroupPos groupPos
= IntlGeneric()->GroupPosition();
431 *aGroupLevel
= groupPos
.level
;
432 *aSimilarItemsInGroup
= groupPos
.setSize
;
433 *aPositionInGroup
= groupPos
.posInSet
;
439 xpcAccessible::GetRelationByType(uint32_t aType
,
440 nsIAccessibleRelation
** aRelation
) {
441 NS_ENSURE_ARG_POINTER(aRelation
);
442 *aRelation
= nullptr;
444 NS_ENSURE_ARG(aType
<= static_cast<uint32_t>(RelationType::LAST
));
446 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
449 IntlGeneric()->RelationByType(static_cast<RelationType
>(aType
));
450 NS_ADDREF(*aRelation
= new nsAccessibleRelation(aType
, &rel
));
455 xpcAccessible::GetRelations(nsIArray
** aRelations
) {
456 NS_ENSURE_ARG_POINTER(aRelations
);
457 *aRelations
= nullptr;
459 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
461 nsCOMPtr
<nsIMutableArray
> relations
= do_CreateInstance(NS_ARRAY_CONTRACTID
);
462 NS_ENSURE_TRUE(relations
, NS_ERROR_OUT_OF_MEMORY
);
464 for (uint32_t type
= 0; type
<= static_cast<uint32_t>(RelationType::LAST
);
466 nsCOMPtr
<nsIAccessibleRelation
> relation
;
467 nsresult rv
= GetRelationByType(type
, getter_AddRefs(relation
));
469 if (NS_SUCCEEDED(rv
) && relation
) {
470 uint32_t targets
= 0;
471 relation
->GetTargetsCount(&targets
);
472 if (targets
) relations
->AppendElement(relation
);
476 NS_ADDREF(*aRelations
= relations
);
481 xpcAccessible::GetFocusedChild(nsIAccessible
** aChild
) {
482 NS_ENSURE_ARG_POINTER(aChild
);
485 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
487 NS_IF_ADDREF(*aChild
= ToXPC(IntlGeneric()->FocusedChild()));
493 xpcAccessible::GetChildAtPoint(int32_t aX
, int32_t aY
,
494 nsIAccessible
** aAccessible
) {
495 NS_ENSURE_ARG_POINTER(aAccessible
);
496 *aAccessible
= nullptr;
498 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
500 NS_IF_ADDREF(*aAccessible
= ToXPC(IntlGeneric()->ChildAtPoint(
501 aX
, aY
, Accessible::EWhichChildAtPoint::DirectChild
)));
507 xpcAccessible::GetDeepestChildAtPoint(int32_t aX
, int32_t aY
,
508 nsIAccessible
** aAccessible
) {
509 NS_ENSURE_ARG_POINTER(aAccessible
);
510 *aAccessible
= nullptr;
512 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
514 NS_IF_ADDREF(*aAccessible
= ToXPC(IntlGeneric()->ChildAtPoint(
515 aX
, aY
, Accessible::EWhichChildAtPoint::DeepestChild
)));
521 xpcAccessible::GetDeepestChildAtPointInProcess(int32_t aX
, int32_t aY
,
522 nsIAccessible
** aAccessible
) {
523 NS_ENSURE_ARG_POINTER(aAccessible
);
524 *aAccessible
= nullptr;
526 Accessible
* generic
= IntlGeneric();
527 if (!generic
|| generic
->IsRemote()) {
528 return NS_ERROR_FAILURE
;
531 NS_IF_ADDREF(*aAccessible
= ToXPC(Intl()->LocalChildAtPoint(
532 aX
, aY
, Accessible::EWhichChildAtPoint::DeepestChild
)));
537 xpcAccessible::SetSelected(bool aSelect
) {
538 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
540 IntlGeneric()->SetSelected(aSelect
);
546 xpcAccessible::TakeSelection() {
547 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
549 IntlGeneric()->TakeSelection();
555 xpcAccessible::TakeFocus() {
556 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
558 IntlGeneric()->TakeFocus();
563 xpcAccessible::GetActionCount(uint8_t* aActionCount
) {
564 NS_ENSURE_ARG_POINTER(aActionCount
);
566 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
568 *aActionCount
= IntlGeneric()->ActionCount();
574 xpcAccessible::GetActionName(uint8_t aIndex
, nsAString
& aName
) {
577 if (!IntlGeneric()) {
578 return NS_ERROR_FAILURE
;
581 if (aIndex
>= IntlGeneric()->ActionCount()) {
582 return NS_ERROR_INVALID_ARG
;
586 IntlGeneric()->ActionNameAt(aIndex
, name
);
594 xpcAccessible::GetActionDescription(uint8_t aIndex
, nsAString
& aDescription
) {
595 aDescription
.Truncate();
597 if (!IntlGeneric()) {
598 return NS_ERROR_FAILURE
;
601 if (aIndex
>= IntlGeneric()->ActionCount()) {
602 return NS_ERROR_INVALID_ARG
;
605 nsAutoString description
;
606 IntlGeneric()->ActionDescriptionAt(aIndex
, description
);
608 aDescription
.Assign(description
);
614 xpcAccessible::DoAction(uint8_t aIndex
) {
615 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
617 return IntlGeneric()->DoAction(aIndex
) ? NS_OK
: NS_ERROR_INVALID_ARG
;
621 xpcAccessible::ScrollTo(uint32_t aHow
) {
622 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
624 IntlGeneric()->ScrollTo(aHow
);
629 xpcAccessible::ScrollToPoint(uint32_t aCoordinateType
, int32_t aX
, int32_t aY
) {
630 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
632 IntlGeneric()->ScrollToPoint(aCoordinateType
, aX
, aY
);
638 xpcAccessible::Announce(const nsAString
& aAnnouncement
, uint16_t aPriority
) {
639 if (RemoteAccessible
* proxy
= IntlGeneric()->AsRemote()) {
641 return NS_ERROR_NOT_IMPLEMENTED
;
643 nsString
announcement(aAnnouncement
);
644 proxy
->Announce(announcement
, aPriority
);
647 Intl()->Announce(aAnnouncement
, aPriority
);
654 xpcAccessible::GetComputedARIARole(nsAString
& aRole
) {
655 if (!IntlGeneric()) {
656 return NS_ERROR_FAILURE
;
659 nsStaticAtom
* ariaRole
= IntlGeneric()->ComputedARIARole();
661 ariaRole
->ToString(aRole
);