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 static const uint32_t relationTypes
[] = {
465 nsIAccessibleRelation::RELATION_LABELLED_BY
,
466 nsIAccessibleRelation::RELATION_LABEL_FOR
,
467 nsIAccessibleRelation::RELATION_DESCRIBED_BY
,
468 nsIAccessibleRelation::RELATION_DESCRIPTION_FOR
,
469 nsIAccessibleRelation::RELATION_NODE_CHILD_OF
,
470 nsIAccessibleRelation::RELATION_NODE_PARENT_OF
,
471 nsIAccessibleRelation::RELATION_CONTROLLED_BY
,
472 nsIAccessibleRelation::RELATION_CONTROLLER_FOR
,
473 nsIAccessibleRelation::RELATION_FLOWS_TO
,
474 nsIAccessibleRelation::RELATION_FLOWS_FROM
,
475 nsIAccessibleRelation::RELATION_MEMBER_OF
,
476 nsIAccessibleRelation::RELATION_SUBWINDOW_OF
,
477 nsIAccessibleRelation::RELATION_EMBEDS
,
478 nsIAccessibleRelation::RELATION_EMBEDDED_BY
,
479 nsIAccessibleRelation::RELATION_POPUP_FOR
,
480 nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF
,
481 nsIAccessibleRelation::RELATION_DEFAULT_BUTTON
,
482 nsIAccessibleRelation::RELATION_CONTAINING_DOCUMENT
,
483 nsIAccessibleRelation::RELATION_CONTAINING_TAB_PANE
,
484 nsIAccessibleRelation::RELATION_CONTAINING_APPLICATION
};
486 for (uint32_t idx
= 0; idx
< ArrayLength(relationTypes
); idx
++) {
487 nsCOMPtr
<nsIAccessibleRelation
> relation
;
489 GetRelationByType(relationTypes
[idx
], getter_AddRefs(relation
));
491 if (NS_SUCCEEDED(rv
) && relation
) {
492 uint32_t targets
= 0;
493 relation
->GetTargetsCount(&targets
);
494 if (targets
) relations
->AppendElement(relation
);
498 NS_ADDREF(*aRelations
= relations
);
503 xpcAccessible::GetFocusedChild(nsIAccessible
** aChild
) {
504 NS_ENSURE_ARG_POINTER(aChild
);
507 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
509 NS_IF_ADDREF(*aChild
= ToXPC(IntlGeneric()->FocusedChild()));
515 xpcAccessible::GetChildAtPoint(int32_t aX
, int32_t aY
,
516 nsIAccessible
** aAccessible
) {
517 NS_ENSURE_ARG_POINTER(aAccessible
);
518 *aAccessible
= nullptr;
520 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
522 NS_IF_ADDREF(*aAccessible
= ToXPC(IntlGeneric()->ChildAtPoint(
523 aX
, aY
, Accessible::EWhichChildAtPoint::DirectChild
)));
529 xpcAccessible::GetDeepestChildAtPoint(int32_t aX
, int32_t aY
,
530 nsIAccessible
** aAccessible
) {
531 NS_ENSURE_ARG_POINTER(aAccessible
);
532 *aAccessible
= nullptr;
534 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
536 NS_IF_ADDREF(*aAccessible
= ToXPC(IntlGeneric()->ChildAtPoint(
537 aX
, aY
, Accessible::EWhichChildAtPoint::DeepestChild
)));
543 xpcAccessible::GetDeepestChildAtPointInProcess(int32_t aX
, int32_t aY
,
544 nsIAccessible
** aAccessible
) {
545 NS_ENSURE_ARG_POINTER(aAccessible
);
546 *aAccessible
= nullptr;
548 Accessible
* generic
= IntlGeneric();
549 if (!generic
|| generic
->IsRemote()) {
550 return NS_ERROR_FAILURE
;
553 NS_IF_ADDREF(*aAccessible
= ToXPC(Intl()->LocalChildAtPoint(
554 aX
, aY
, Accessible::EWhichChildAtPoint::DeepestChild
)));
559 xpcAccessible::SetSelected(bool aSelect
) {
560 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
562 IntlGeneric()->SetSelected(aSelect
);
568 xpcAccessible::TakeSelection() {
569 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
571 IntlGeneric()->TakeSelection();
577 xpcAccessible::TakeFocus() {
578 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
580 IntlGeneric()->TakeFocus();
585 xpcAccessible::GetActionCount(uint8_t* aActionCount
) {
586 NS_ENSURE_ARG_POINTER(aActionCount
);
588 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
590 *aActionCount
= IntlGeneric()->ActionCount();
596 xpcAccessible::GetActionName(uint8_t aIndex
, nsAString
& aName
) {
599 if (!IntlGeneric()) {
600 return NS_ERROR_FAILURE
;
603 if (aIndex
>= IntlGeneric()->ActionCount()) {
604 return NS_ERROR_INVALID_ARG
;
608 IntlGeneric()->ActionNameAt(aIndex
, name
);
616 xpcAccessible::GetActionDescription(uint8_t aIndex
, nsAString
& aDescription
) {
617 aDescription
.Truncate();
619 if (!IntlGeneric()) {
620 return NS_ERROR_FAILURE
;
623 if (aIndex
>= IntlGeneric()->ActionCount()) {
624 return NS_ERROR_INVALID_ARG
;
627 nsAutoString description
;
628 IntlGeneric()->ActionDescriptionAt(aIndex
, description
);
630 aDescription
.Assign(description
);
636 xpcAccessible::DoAction(uint8_t aIndex
) {
637 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
639 return IntlGeneric()->DoAction(aIndex
) ? NS_OK
: NS_ERROR_INVALID_ARG
;
643 xpcAccessible::ScrollTo(uint32_t aHow
) {
644 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
646 IntlGeneric()->ScrollTo(aHow
);
651 xpcAccessible::ScrollToPoint(uint32_t aCoordinateType
, int32_t aX
, int32_t aY
) {
652 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
654 IntlGeneric()->ScrollToPoint(aCoordinateType
, aX
, aY
);
660 xpcAccessible::Announce(const nsAString
& aAnnouncement
, uint16_t aPriority
) {
661 if (RemoteAccessible
* proxy
= IntlGeneric()->AsRemote()) {
663 return NS_ERROR_NOT_IMPLEMENTED
;
665 nsString
announcement(aAnnouncement
);
666 proxy
->Announce(announcement
, aPriority
);
669 Intl()->Announce(aAnnouncement
, aPriority
);
676 xpcAccessible::GetComputedARIARole(nsAString
& aRole
) {
677 if (!IntlGeneric()) {
678 return NS_ERROR_FAILURE
;
681 nsStaticAtom
* ariaRole
= IntlGeneric()->ComputedARIARole();
683 ariaRole
->ToString(aRole
);