Bug 1849600 - Mark text-input-vertical-overflow-no-scroll.html substests as intermitt...
[gecko.git] / accessible / xpcom / xpcAccessible.cpp
blobf7e118c8ddf9d176ca5f290e90e02a6c4e0a8c17
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"
13 #include "Relation.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"
22 #endif
24 using namespace mozilla::a11y;
26 NS_IMETHODIMP
27 xpcAccessible::GetParent(nsIAccessible** aParent) {
28 NS_ENSURE_ARG_POINTER(aParent);
29 *aParent = nullptr;
30 if (!IntlGeneric()) return NS_ERROR_FAILURE;
32 Accessible* parent = IntlGeneric()->Parent();
33 NS_IF_ADDREF(*aParent = ToXPC(parent));
34 return NS_OK;
37 NS_IMETHODIMP
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()));
45 return NS_OK;
48 NS_IMETHODIMP
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()));
56 return NS_OK;
59 NS_IMETHODIMP
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()));
67 return NS_OK;
70 NS_IMETHODIMP
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()));
78 return NS_OK;
81 NS_IMETHODIMP
82 xpcAccessible::GetChildCount(int32_t* aChildCount) {
83 NS_ENSURE_ARG_POINTER(aChildCount);
85 if (!IntlGeneric()) return NS_ERROR_FAILURE;
87 *aChildCount = IntlGeneric()->ChildCount();
88 return NS_OK;
91 NS_IMETHODIMP
92 xpcAccessible::GetChildAt(int32_t aChildIndex, nsIAccessible** aChild) {
93 NS_ENSURE_ARG_POINTER(aChild);
94 *aChild = nullptr;
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));
106 return NS_OK;
109 NS_IMETHODIMP
110 xpcAccessible::GetChildren(nsIArray** aChildren) {
111 NS_ENSURE_ARG_POINTER(aChildren);
112 *aChildren = nullptr;
114 if (!IntlGeneric()) return NS_ERROR_FAILURE;
116 nsresult rv = NS_OK;
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);
128 return NS_OK;
131 NS_IMETHODIMP
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;
142 NS_IMETHODIMP
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();
154 return NS_OK;
157 NS_IMETHODIMP
158 xpcAccessible::GetDOMNode(nsINode** aDOMNode) {
159 NS_ENSURE_ARG_POINTER(aDOMNode);
160 *aDOMNode = nullptr;
162 if (!Intl()) return NS_ERROR_FAILURE;
164 nsCOMPtr<nsINode> node = Intl()->GetNode();
165 node.forget(aDOMNode);
167 return NS_OK;
170 NS_IMETHODIMP
171 xpcAccessible::GetId(nsAString& aID) {
172 if (!IntlGeneric()) {
173 return NS_ERROR_FAILURE;
176 RemoteAccessible* proxy = IntlGeneric()->AsRemote();
177 if (!proxy) {
178 return NS_ERROR_FAILURE;
181 nsString id;
182 proxy->DOMNodeID(id);
183 aID.Assign(id);
185 return NS_OK;
188 NS_IMETHODIMP
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()));
196 return NS_OK;
199 NS_IMETHODIMP
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()));
207 return NS_OK;
210 NS_IMETHODIMP
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();
218 return NS_OK;
221 NS_IMETHODIMP
222 xpcAccessible::GetState(uint32_t* aState, uint32_t* aExtraState) {
223 NS_ENSURE_ARG_POINTER(aState);
225 Accessible* acc = IntlGeneric();
226 if (acc) {
227 nsAccUtils::To32States(acc->State(), aState, aExtraState);
228 } else {
229 nsAccUtils::To32States(states::DEFUNCT, aState, aExtraState);
232 return NS_OK;
235 NS_IMETHODIMP
236 xpcAccessible::GetName(nsAString& aName) {
237 aName.Truncate();
239 if (!IntlGeneric()) return NS_ERROR_FAILURE;
241 nsAutoString name;
242 IntlGeneric()->Name(name);
244 aName.Assign(name);
246 return NS_OK;
249 NS_IMETHODIMP
250 xpcAccessible::GetDescription(nsAString& aDescription) {
251 if (!IntlGeneric()) return NS_ERROR_FAILURE;
253 nsAutoString desc;
254 IntlGeneric()->Description(desc);
256 aDescription.Assign(desc);
258 return NS_OK;
261 NS_IMETHODIMP
262 xpcAccessible::GetLanguage(nsAString& aLanguage) {
263 if (!IntlGeneric()) return NS_ERROR_FAILURE;
265 nsAutoString lang;
266 IntlGeneric()->Language(lang);
268 aLanguage.Assign(lang);
269 return NS_OK;
272 NS_IMETHODIMP
273 xpcAccessible::GetValue(nsAString& aValue) {
274 if (!IntlGeneric()) return NS_ERROR_FAILURE;
276 nsAutoString value;
277 IntlGeneric()->Value(value);
279 aValue.Assign(value);
281 return NS_OK;
284 NS_IMETHODIMP
285 xpcAccessible::GetAccessKey(nsAString& aAccessKey) {
286 aAccessKey.Truncate();
288 if (!IntlGeneric()) return NS_ERROR_FAILURE;
290 IntlGeneric()->AccessKey().ToString(aAccessKey);
291 return NS_OK;
294 NS_IMETHODIMP
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);
303 return NS_OK;
306 NS_IMETHODIMP
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();
319 nsAutoString unused;
320 for (auto iter : *attributes) {
321 nsAutoString name;
322 iter.NameAsString(name);
324 nsAutoString value;
325 iter.ValueAsString(value);
327 props->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused);
330 props.forget(aAttributes);
331 return NS_OK;
334 NS_IMETHODIMP
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) {
346 nsAutoString unused;
347 for (auto iter : *cachedFields) {
348 nsAutoString name;
349 iter.NameAsString(name);
351 nsAutoString value;
352 iter.ValueAsString(value);
354 props->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused);
359 props.forget(aCachedFields);
360 return NS_OK;
363 NS_IMETHODIMP
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);
375 return NS_OK;
376 #else
377 return NS_ERROR_NOT_IMPLEMENTED;
378 #endif
381 NS_IMETHODIMP
382 xpcAccessible::GetBounds(int32_t* aX, int32_t* aY, int32_t* aWidth,
383 int32_t* aHeight) {
384 NS_ENSURE_ARG_POINTER(aX);
385 *aX = 0;
386 NS_ENSURE_ARG_POINTER(aY);
387 *aY = 0;
388 NS_ENSURE_ARG_POINTER(aWidth);
389 *aWidth = 0;
390 NS_ENSURE_ARG_POINTER(aHeight);
391 *aHeight = 0;
393 if (!IntlGeneric()) return NS_ERROR_FAILURE;
395 LayoutDeviceIntRect rect = IntlGeneric()->Bounds();
396 rect.GetRect(aX, aY, aWidth, aHeight);
397 return NS_OK;
400 NS_IMETHODIMP
401 xpcAccessible::GetBoundsInCSSPixels(int32_t* aX, int32_t* aY, int32_t* aWidth,
402 int32_t* aHeight) {
403 NS_ENSURE_ARG_POINTER(aX);
404 *aX = 0;
405 NS_ENSURE_ARG_POINTER(aY);
406 *aY = 0;
407 NS_ENSURE_ARG_POINTER(aWidth);
408 *aWidth = 0;
409 NS_ENSURE_ARG_POINTER(aHeight);
410 *aHeight = 0;
412 if (!IntlGeneric()) {
413 return NS_ERROR_FAILURE;
416 nsIntRect rect = IntlGeneric()->BoundsInCSSPixels();
417 rect.GetRect(aX, aY, aWidth, aHeight);
418 return NS_OK;
421 NS_IMETHODIMP
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;
435 return NS_OK;
438 NS_IMETHODIMP
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;
448 Relation rel =
449 IntlGeneric()->RelationByType(static_cast<RelationType>(aType));
450 NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &rel));
451 return NS_OK;
454 NS_IMETHODIMP
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;
488 nsresult rv =
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);
499 return NS_OK;
502 NS_IMETHODIMP
503 xpcAccessible::GetFocusedChild(nsIAccessible** aChild) {
504 NS_ENSURE_ARG_POINTER(aChild);
505 *aChild = nullptr;
507 if (!IntlGeneric()) return NS_ERROR_FAILURE;
509 NS_IF_ADDREF(*aChild = ToXPC(IntlGeneric()->FocusedChild()));
511 return NS_OK;
514 NS_IMETHODIMP
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)));
525 return NS_OK;
528 NS_IMETHODIMP
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)));
539 return NS_OK;
542 NS_IMETHODIMP
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)));
555 return NS_OK;
558 NS_IMETHODIMP
559 xpcAccessible::SetSelected(bool aSelect) {
560 if (!IntlGeneric()) return NS_ERROR_FAILURE;
562 IntlGeneric()->SetSelected(aSelect);
564 return NS_OK;
567 NS_IMETHODIMP
568 xpcAccessible::TakeSelection() {
569 if (!IntlGeneric()) return NS_ERROR_FAILURE;
571 IntlGeneric()->TakeSelection();
573 return NS_OK;
576 NS_IMETHODIMP
577 xpcAccessible::TakeFocus() {
578 if (!IntlGeneric()) return NS_ERROR_FAILURE;
580 IntlGeneric()->TakeFocus();
581 return NS_OK;
584 NS_IMETHODIMP
585 xpcAccessible::GetActionCount(uint8_t* aActionCount) {
586 NS_ENSURE_ARG_POINTER(aActionCount);
587 *aActionCount = 0;
588 if (!IntlGeneric()) return NS_ERROR_FAILURE;
590 *aActionCount = IntlGeneric()->ActionCount();
592 return NS_OK;
595 NS_IMETHODIMP
596 xpcAccessible::GetActionName(uint8_t aIndex, nsAString& aName) {
597 aName.Truncate();
599 if (!IntlGeneric()) {
600 return NS_ERROR_FAILURE;
603 if (aIndex >= IntlGeneric()->ActionCount()) {
604 return NS_ERROR_INVALID_ARG;
607 nsAutoString name;
608 IntlGeneric()->ActionNameAt(aIndex, name);
610 aName.Assign(name);
612 return NS_OK;
615 NS_IMETHODIMP
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);
632 return NS_OK;
635 NS_IMETHODIMP
636 xpcAccessible::DoAction(uint8_t aIndex) {
637 if (!IntlGeneric()) return NS_ERROR_FAILURE;
639 return IntlGeneric()->DoAction(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG;
642 NS_IMETHODIMP
643 xpcAccessible::ScrollTo(uint32_t aHow) {
644 if (!IntlGeneric()) return NS_ERROR_FAILURE;
646 IntlGeneric()->ScrollTo(aHow);
647 return NS_OK;
650 NS_IMETHODIMP
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);
656 return NS_OK;
659 NS_IMETHODIMP
660 xpcAccessible::Announce(const nsAString& aAnnouncement, uint16_t aPriority) {
661 if (RemoteAccessible* proxy = IntlGeneric()->AsRemote()) {
662 #if defined(XP_WIN)
663 return NS_ERROR_NOT_IMPLEMENTED;
664 #else
665 nsString announcement(aAnnouncement);
666 proxy->Announce(announcement, aPriority);
667 #endif
668 } else {
669 Intl()->Announce(aAnnouncement, aPriority);
672 return NS_OK;
675 NS_IMETHODIMP
676 xpcAccessible::GetComputedARIARole(nsAString& aRole) {
677 if (!IntlGeneric()) {
678 return NS_ERROR_FAILURE;
681 nsStaticAtom* ariaRole = IntlGeneric()->ComputedARIARole();
682 if (ariaRole) {
683 ariaRole->ToString(aRole);
686 return NS_OK;