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 "LocalAccessible-inl.h"
8 #include "mozilla/a11y/DocAccessibleParent.h"
9 #include "nsAccessibilityService.h"
10 #include "AccAttributes.h"
11 #include "nsAccUtils.h"
12 #include "nsComponentManagerUtils.h"
13 #include "nsIAccessibleRelation.h"
14 #include "nsIAccessibleRole.h"
15 #include "nsAccessibleRelation.h"
18 #include "RootAccessible.h"
19 #include "xpcAccessibleDocument.h"
21 #include "nsIMutableArray.h"
22 #include "nsPersistentProperties.h"
24 #ifdef MOZ_WIDGET_COCOA
25 # include "xpcAccessibleMacInterface.h"
28 using namespace mozilla::a11y
;
31 xpcAccessible::GetParent(nsIAccessible
** aParent
) {
32 NS_ENSURE_ARG_POINTER(aParent
);
34 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
36 Accessible
* parent
= IntlGeneric()->Parent();
37 NS_IF_ADDREF(*aParent
= ToXPC(parent
));
42 xpcAccessible::GetNextSibling(nsIAccessible
** aNextSibling
) {
43 NS_ENSURE_ARG_POINTER(aNextSibling
);
44 *aNextSibling
= nullptr;
45 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
47 NS_IF_ADDREF(*aNextSibling
= ToXPC(IntlGeneric()->NextSibling()));
53 xpcAccessible::GetPreviousSibling(nsIAccessible
** aPreviousSibling
) {
54 NS_ENSURE_ARG_POINTER(aPreviousSibling
);
55 *aPreviousSibling
= nullptr;
56 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
58 NS_IF_ADDREF(*aPreviousSibling
= ToXPC(IntlGeneric()->PrevSibling()));
64 xpcAccessible::GetFirstChild(nsIAccessible
** aFirstChild
) {
65 NS_ENSURE_ARG_POINTER(aFirstChild
);
66 *aFirstChild
= nullptr;
68 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
70 NS_IF_ADDREF(*aFirstChild
= ToXPC(IntlGeneric()->FirstChild()));
75 xpcAccessible::GetLastChild(nsIAccessible
** aLastChild
) {
76 NS_ENSURE_ARG_POINTER(aLastChild
);
77 *aLastChild
= nullptr;
79 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
81 NS_IF_ADDREF(*aLastChild
= ToXPC(IntlGeneric()->LastChild()));
86 xpcAccessible::GetChildCount(int32_t* aChildCount
) {
87 NS_ENSURE_ARG_POINTER(aChildCount
);
89 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
91 *aChildCount
= IntlGeneric()->ChildCount();
96 xpcAccessible::GetChildAt(int32_t aChildIndex
, nsIAccessible
** aChild
) {
97 NS_ENSURE_ARG_POINTER(aChild
);
100 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
102 // If child index is negative, then return last child.
103 // XXX: do we really need this?
104 if (aChildIndex
< 0) aChildIndex
= IntlGeneric()->ChildCount() - 1;
106 Accessible
* child
= IntlGeneric()->ChildAt(aChildIndex
);
107 if (!child
) return NS_ERROR_INVALID_ARG
;
109 NS_ADDREF(*aChild
= ToXPC(child
));
114 xpcAccessible::GetChildren(nsIArray
** aChildren
) {
115 NS_ENSURE_ARG_POINTER(aChildren
);
116 *aChildren
= nullptr;
118 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
121 nsCOMPtr
<nsIMutableArray
> children
=
122 do_CreateInstance(NS_ARRAY_CONTRACTID
, &rv
);
123 NS_ENSURE_SUCCESS(rv
, rv
);
125 uint32_t childCount
= IntlGeneric()->ChildCount();
126 for (uint32_t childIdx
= 0; childIdx
< childCount
; childIdx
++) {
127 Accessible
* child
= IntlGeneric()->ChildAt(childIdx
);
128 children
->AppendElement(static_cast<nsIAccessible
*>(ToXPC(child
)));
131 children
.forget(aChildren
);
136 xpcAccessible::GetIndexInParent(int32_t* aIndexInParent
) {
137 NS_ENSURE_ARG_POINTER(aIndexInParent
);
138 *aIndexInParent
= -1;
139 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
141 *aIndexInParent
= IntlGeneric()->IndexInParent();
143 return *aIndexInParent
!= -1 ? NS_OK
: NS_ERROR_FAILURE
;
147 xpcAccessible::GetUniqueID(int64_t* aUniqueID
) {
148 NS_ENSURE_ARG_POINTER(aUniqueID
);
150 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
152 if (IntlGeneric()->IsLocal()) {
153 *aUniqueID
= reinterpret_cast<uintptr_t>(Intl()->UniqueID());
154 } else if (IntlGeneric()->IsRemote()) {
155 *aUniqueID
= IntlGeneric()->AsRemote()->ID();
162 xpcAccessible::GetDOMNode(nsINode
** aDOMNode
) {
163 NS_ENSURE_ARG_POINTER(aDOMNode
);
166 if (!Intl()) return NS_ERROR_FAILURE
;
168 nsCOMPtr
<nsINode
> node
= Intl()->GetNode();
169 node
.forget(aDOMNode
);
175 xpcAccessible::GetId(nsAString
& aID
) {
176 if (!IntlGeneric()) {
177 return NS_ERROR_FAILURE
;
180 RemoteAccessible
* proxy
= IntlGeneric()->AsRemote();
182 return NS_ERROR_FAILURE
;
186 proxy
->DOMNodeID(id
);
193 xpcAccessible::GetDocument(nsIAccessibleDocument
** aDocument
) {
194 NS_ENSURE_ARG_POINTER(aDocument
);
195 *aDocument
= nullptr;
197 if (!Intl()) return NS_ERROR_FAILURE
;
199 NS_IF_ADDREF(*aDocument
= ToXPCDocument(Intl()->Document()));
204 xpcAccessible::GetRootDocument(nsIAccessibleDocument
** aRootDocument
) {
205 NS_ENSURE_ARG_POINTER(aRootDocument
);
206 *aRootDocument
= nullptr;
208 if (!Intl()) return NS_ERROR_FAILURE
;
210 NS_IF_ADDREF(*aRootDocument
= ToXPCDocument(Intl()->RootAccessible()));
215 xpcAccessible::GetRole(uint32_t* aRole
) {
216 NS_ENSURE_ARG_POINTER(aRole
);
217 *aRole
= nsIAccessibleRole::ROLE_NOTHING
;
219 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
221 *aRole
= IntlGeneric()->Role();
226 xpcAccessible::GetState(uint32_t* aState
, uint32_t* aExtraState
) {
227 NS_ENSURE_ARG_POINTER(aState
);
229 Accessible
* acc
= IntlGeneric();
231 nsAccUtils::To32States(acc
->State(), aState
, aExtraState
);
233 nsAccUtils::To32States(states::DEFUNCT
, aState
, aExtraState
);
240 xpcAccessible::GetName(nsAString
& aName
) {
243 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
246 IntlGeneric()->Name(name
);
254 xpcAccessible::GetDescription(nsAString
& aDescription
) {
255 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
258 IntlGeneric()->Description(desc
);
260 aDescription
.Assign(desc
);
266 xpcAccessible::GetLanguage(nsAString
& aLanguage
) {
267 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
270 IntlGeneric()->Language(lang
);
272 aLanguage
.Assign(lang
);
277 xpcAccessible::GetValue(nsAString
& aValue
) {
278 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
281 IntlGeneric()->Value(value
);
283 aValue
.Assign(value
);
289 xpcAccessible::GetAccessKey(nsAString
& aAccessKey
) {
290 aAccessKey
.Truncate();
292 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
294 IntlGeneric()->AccessKey().ToString(aAccessKey
);
299 xpcAccessible::GetKeyboardShortcut(nsAString
& aKeyBinding
) {
300 aKeyBinding
.Truncate();
301 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
303 if (IntlGeneric()->IsRemote()) {
304 return NS_ERROR_NOT_IMPLEMENTED
;
306 Intl()->KeyboardShortcut().ToString(aKeyBinding
);
311 xpcAccessible::GetAttributes(nsIPersistentProperties
** aAttributes
) {
312 NS_ENSURE_ARG_POINTER(aAttributes
);
313 *aAttributes
= nullptr;
315 if (!IntlGeneric()) {
316 return NS_ERROR_FAILURE
;
319 RefPtr
<nsPersistentProperties
> props
= new nsPersistentProperties();
321 RefPtr
<AccAttributes
> attributes
= IntlGeneric()->Attributes();
324 for (auto iter
: *attributes
) {
326 iter
.NameAsString(name
);
329 iter
.ValueAsString(value
);
331 props
->SetStringProperty(NS_ConvertUTF16toUTF8(name
), value
, unused
);
334 props
.forget(aAttributes
);
339 xpcAccessible::GetCache(nsIPersistentProperties
** aCachedFields
) {
340 NS_ENSURE_ARG_POINTER(aCachedFields
);
341 *aCachedFields
= nullptr;
343 if (!IntlGeneric()) {
344 return NS_ERROR_FAILURE
;
347 RefPtr
<nsPersistentProperties
> props
= new nsPersistentProperties();
348 if (RemoteAccessible
* remoteAcc
= IntlGeneric()->AsRemote()) {
349 if (RefPtr
<AccAttributes
> cachedFields
= remoteAcc
->mCachedFields
) {
351 for (auto iter
: *cachedFields
) {
353 iter
.NameAsString(name
);
356 iter
.ValueAsString(value
);
358 props
->SetStringProperty(NS_ConvertUTF16toUTF8(name
), value
, unused
);
363 props
.forget(aCachedFields
);
368 xpcAccessible::GetNativeInterface(nsISupports
** aNativeInterface
) {
369 #ifdef MOZ_WIDGET_COCOA
370 NS_ENSURE_ARG_POINTER(aNativeInterface
);
372 // We don't cache or store this instance anywhere so each get returns a
373 // different instance. So `acc.nativeInterface != acc.nativeInterface`. This
374 // just seems simpler and more robust for now.
375 nsCOMPtr
<nsISupports
> macIface
= static_cast<nsIAccessibleMacInterface
*>(
376 new xpcAccessibleMacInterface(IntlGeneric()));
377 macIface
.swap(*aNativeInterface
);
381 return NS_ERROR_NOT_IMPLEMENTED
;
386 xpcAccessible::GetBounds(int32_t* aX
, int32_t* aY
, int32_t* aWidth
,
388 NS_ENSURE_ARG_POINTER(aX
);
390 NS_ENSURE_ARG_POINTER(aY
);
392 NS_ENSURE_ARG_POINTER(aWidth
);
394 NS_ENSURE_ARG_POINTER(aHeight
);
397 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
399 LayoutDeviceIntRect rect
= IntlGeneric()->Bounds();
400 rect
.GetRect(aX
, aY
, aWidth
, aHeight
);
405 xpcAccessible::GetBoundsInCSSPixels(int32_t* aX
, int32_t* aY
, int32_t* aWidth
,
407 NS_ENSURE_ARG_POINTER(aX
);
409 NS_ENSURE_ARG_POINTER(aY
);
411 NS_ENSURE_ARG_POINTER(aWidth
);
413 NS_ENSURE_ARG_POINTER(aHeight
);
416 if (!IntlGeneric()) {
417 return NS_ERROR_FAILURE
;
420 nsIntRect rect
= IntlGeneric()->BoundsInCSSPixels();
421 rect
.GetRect(aX
, aY
, aWidth
, aHeight
);
426 xpcAccessible::GroupPosition(int32_t* aGroupLevel
,
427 int32_t* aSimilarItemsInGroup
,
428 int32_t* aPositionInGroup
) {
429 NS_ENSURE_ARG_POINTER(aGroupLevel
);
430 NS_ENSURE_ARG_POINTER(aSimilarItemsInGroup
);
431 NS_ENSURE_ARG_POINTER(aPositionInGroup
);
433 GroupPos groupPos
= IntlGeneric()->GroupPosition();
435 *aGroupLevel
= groupPos
.level
;
436 *aSimilarItemsInGroup
= groupPos
.setSize
;
437 *aPositionInGroup
= groupPos
.posInSet
;
443 xpcAccessible::GetRelationByType(uint32_t aType
,
444 nsIAccessibleRelation
** aRelation
) {
445 NS_ENSURE_ARG_POINTER(aRelation
);
446 *aRelation
= nullptr;
448 NS_ENSURE_ARG(aType
<= static_cast<uint32_t>(RelationType::LAST
));
450 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
453 IntlGeneric()->RelationByType(static_cast<RelationType
>(aType
));
454 NS_ADDREF(*aRelation
= new nsAccessibleRelation(aType
, &rel
));
459 xpcAccessible::GetRelations(nsIArray
** aRelations
) {
460 NS_ENSURE_ARG_POINTER(aRelations
);
461 *aRelations
= nullptr;
463 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
465 nsCOMPtr
<nsIMutableArray
> relations
= do_CreateInstance(NS_ARRAY_CONTRACTID
);
466 NS_ENSURE_TRUE(relations
, NS_ERROR_OUT_OF_MEMORY
);
468 static const uint32_t relationTypes
[] = {
469 nsIAccessibleRelation::RELATION_LABELLED_BY
,
470 nsIAccessibleRelation::RELATION_LABEL_FOR
,
471 nsIAccessibleRelation::RELATION_DESCRIBED_BY
,
472 nsIAccessibleRelation::RELATION_DESCRIPTION_FOR
,
473 nsIAccessibleRelation::RELATION_NODE_CHILD_OF
,
474 nsIAccessibleRelation::RELATION_NODE_PARENT_OF
,
475 nsIAccessibleRelation::RELATION_CONTROLLED_BY
,
476 nsIAccessibleRelation::RELATION_CONTROLLER_FOR
,
477 nsIAccessibleRelation::RELATION_FLOWS_TO
,
478 nsIAccessibleRelation::RELATION_FLOWS_FROM
,
479 nsIAccessibleRelation::RELATION_MEMBER_OF
,
480 nsIAccessibleRelation::RELATION_SUBWINDOW_OF
,
481 nsIAccessibleRelation::RELATION_EMBEDS
,
482 nsIAccessibleRelation::RELATION_EMBEDDED_BY
,
483 nsIAccessibleRelation::RELATION_POPUP_FOR
,
484 nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF
,
485 nsIAccessibleRelation::RELATION_DEFAULT_BUTTON
,
486 nsIAccessibleRelation::RELATION_CONTAINING_DOCUMENT
,
487 nsIAccessibleRelation::RELATION_CONTAINING_TAB_PANE
,
488 nsIAccessibleRelation::RELATION_CONTAINING_APPLICATION
};
490 for (uint32_t idx
= 0; idx
< ArrayLength(relationTypes
); idx
++) {
491 nsCOMPtr
<nsIAccessibleRelation
> relation
;
493 GetRelationByType(relationTypes
[idx
], getter_AddRefs(relation
));
495 if (NS_SUCCEEDED(rv
) && relation
) {
496 uint32_t targets
= 0;
497 relation
->GetTargetsCount(&targets
);
498 if (targets
) relations
->AppendElement(relation
);
502 NS_ADDREF(*aRelations
= relations
);
507 xpcAccessible::GetFocusedChild(nsIAccessible
** aChild
) {
508 NS_ENSURE_ARG_POINTER(aChild
);
511 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
513 NS_IF_ADDREF(*aChild
= ToXPC(IntlGeneric()->FocusedChild()));
519 xpcAccessible::GetChildAtPoint(int32_t aX
, int32_t aY
,
520 nsIAccessible
** aAccessible
) {
521 NS_ENSURE_ARG_POINTER(aAccessible
);
522 *aAccessible
= nullptr;
524 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
526 NS_IF_ADDREF(*aAccessible
= ToXPC(IntlGeneric()->ChildAtPoint(
527 aX
, aY
, Accessible::EWhichChildAtPoint::DirectChild
)));
533 xpcAccessible::GetDeepestChildAtPoint(int32_t aX
, int32_t aY
,
534 nsIAccessible
** aAccessible
) {
535 NS_ENSURE_ARG_POINTER(aAccessible
);
536 *aAccessible
= nullptr;
538 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
540 NS_IF_ADDREF(*aAccessible
= ToXPC(IntlGeneric()->ChildAtPoint(
541 aX
, aY
, Accessible::EWhichChildAtPoint::DeepestChild
)));
547 xpcAccessible::GetDeepestChildAtPointInProcess(int32_t aX
, int32_t aY
,
548 nsIAccessible
** aAccessible
) {
549 NS_ENSURE_ARG_POINTER(aAccessible
);
550 *aAccessible
= nullptr;
552 Accessible
* generic
= IntlGeneric();
553 if (!generic
|| generic
->IsRemote()) {
554 return NS_ERROR_FAILURE
;
557 NS_IF_ADDREF(*aAccessible
= ToXPC(Intl()->LocalChildAtPoint(
558 aX
, aY
, Accessible::EWhichChildAtPoint::DeepestChild
)));
563 xpcAccessible::SetSelected(bool aSelect
) {
564 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
566 IntlGeneric()->SetSelected(aSelect
);
572 xpcAccessible::TakeSelection() {
573 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
575 IntlGeneric()->TakeSelection();
581 xpcAccessible::TakeFocus() {
582 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
584 IntlGeneric()->TakeFocus();
589 xpcAccessible::GetActionCount(uint8_t* aActionCount
) {
590 NS_ENSURE_ARG_POINTER(aActionCount
);
592 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
594 *aActionCount
= IntlGeneric()->ActionCount();
600 xpcAccessible::GetActionName(uint8_t aIndex
, nsAString
& aName
) {
603 if (!IntlGeneric()) {
604 return NS_ERROR_FAILURE
;
607 if (aIndex
>= IntlGeneric()->ActionCount()) {
608 return NS_ERROR_INVALID_ARG
;
612 IntlGeneric()->ActionNameAt(aIndex
, name
);
620 xpcAccessible::GetActionDescription(uint8_t aIndex
, nsAString
& aDescription
) {
621 aDescription
.Truncate();
623 if (!IntlGeneric()) {
624 return NS_ERROR_FAILURE
;
627 if (aIndex
>= IntlGeneric()->ActionCount()) {
628 return NS_ERROR_INVALID_ARG
;
631 nsAutoString description
;
632 IntlGeneric()->ActionDescriptionAt(aIndex
, description
);
634 aDescription
.Assign(description
);
640 xpcAccessible::DoAction(uint8_t aIndex
) {
641 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
643 return IntlGeneric()->DoAction(aIndex
) ? NS_OK
: NS_ERROR_INVALID_ARG
;
647 xpcAccessible::ScrollTo(uint32_t aHow
) {
648 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
650 IntlGeneric()->ScrollTo(aHow
);
655 xpcAccessible::ScrollToPoint(uint32_t aCoordinateType
, int32_t aX
, int32_t aY
) {
656 if (!IntlGeneric()) return NS_ERROR_FAILURE
;
658 if (RemoteAccessible
* proxy
= IntlGeneric()->AsRemote()) {
660 return NS_ERROR_NOT_IMPLEMENTED
;
662 proxy
->ScrollToPoint(aCoordinateType
, aX
, aY
);
665 Intl()->ScrollToPoint(aCoordinateType
, aX
, aY
);
672 xpcAccessible::Announce(const nsAString
& aAnnouncement
, uint16_t aPriority
) {
673 if (RemoteAccessible
* proxy
= IntlGeneric()->AsRemote()) {
675 return NS_ERROR_NOT_IMPLEMENTED
;
677 nsString
announcement(aAnnouncement
);
678 proxy
->Announce(announcement
, aPriority
);
681 Intl()->Announce(aAnnouncement
, aPriority
);
688 xpcAccessible::GetComputedARIARole(nsAString
& aRole
) {
689 if (!IntlGeneric()) {
690 return NS_ERROR_FAILURE
;
693 nsStaticAtom
* ariaRole
= IntlGeneric()->ComputedARIARole();
695 ariaRole
->ToString(aRole
);