summaryrefslogtreecommitdiffstats
path: root/accessible/xpcom/xpcAccessible.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--accessible/xpcom/xpcAccessible.cpp665
1 files changed, 665 insertions, 0 deletions
diff --git a/accessible/xpcom/xpcAccessible.cpp b/accessible/xpcom/xpcAccessible.cpp
new file mode 100644
index 0000000000..37901e3ec2
--- /dev/null
+++ b/accessible/xpcom/xpcAccessible.cpp
@@ -0,0 +1,665 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "AccAttributes.h"
+#include "nsAccUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIAccessibleRelation.h"
+#include "nsIAccessibleRole.h"
+#include "nsAccessibleRelation.h"
+#include "Relation.h"
+#include "RootAccessible.h"
+#include "xpcAccessibleDocument.h"
+
+#include "nsIMutableArray.h"
+#include "nsPersistentProperties.h"
+
+#ifdef MOZ_WIDGET_COCOA
+# include "xpcAccessibleMacInterface.h"
+#endif
+
+using namespace mozilla::a11y;
+
+NS_IMETHODIMP
+xpcAccessible::GetParent(nsIAccessible** aParent) {
+ NS_ENSURE_ARG_POINTER(aParent);
+ *aParent = nullptr;
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ Accessible* parent = IntlGeneric()->Parent();
+ NS_IF_ADDREF(*aParent = ToXPC(parent));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetNextSibling(nsIAccessible** aNextSibling) {
+ NS_ENSURE_ARG_POINTER(aNextSibling);
+ *aNextSibling = nullptr;
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aNextSibling = ToXPC(IntlGeneric()->NextSibling()));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetPreviousSibling(nsIAccessible** aPreviousSibling) {
+ NS_ENSURE_ARG_POINTER(aPreviousSibling);
+ *aPreviousSibling = nullptr;
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aPreviousSibling = ToXPC(IntlGeneric()->PrevSibling()));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetFirstChild(nsIAccessible** aFirstChild) {
+ NS_ENSURE_ARG_POINTER(aFirstChild);
+ *aFirstChild = nullptr;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aFirstChild = ToXPC(IntlGeneric()->FirstChild()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetLastChild(nsIAccessible** aLastChild) {
+ NS_ENSURE_ARG_POINTER(aLastChild);
+ *aLastChild = nullptr;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aLastChild = ToXPC(IntlGeneric()->LastChild()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetChildCount(int32_t* aChildCount) {
+ NS_ENSURE_ARG_POINTER(aChildCount);
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ *aChildCount = IntlGeneric()->ChildCount();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetChildAt(int32_t aChildIndex, nsIAccessible** aChild) {
+ NS_ENSURE_ARG_POINTER(aChild);
+ *aChild = nullptr;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ // If child index is negative, then return last child.
+ // XXX: do we really need this?
+ if (aChildIndex < 0) aChildIndex = IntlGeneric()->ChildCount() - 1;
+
+ Accessible* child = IntlGeneric()->ChildAt(aChildIndex);
+ if (!child) return NS_ERROR_INVALID_ARG;
+
+ NS_ADDREF(*aChild = ToXPC(child));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetChildren(nsIArray** aChildren) {
+ NS_ENSURE_ARG_POINTER(aChildren);
+ *aChildren = nullptr;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMutableArray> children =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uint32_t childCount = IntlGeneric()->ChildCount();
+ for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
+ Accessible* child = IntlGeneric()->ChildAt(childIdx);
+ children->AppendElement(static_cast<nsIAccessible*>(ToXPC(child)));
+ }
+
+ children.forget(aChildren);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetIndexInParent(int32_t* aIndexInParent) {
+ NS_ENSURE_ARG_POINTER(aIndexInParent);
+ *aIndexInParent = -1;
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ *aIndexInParent = IntlGeneric()->IndexInParent();
+
+ return *aIndexInParent != -1 ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetUniqueID(int64_t* aUniqueID) {
+ NS_ENSURE_ARG_POINTER(aUniqueID);
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ if (IntlGeneric()->IsLocal()) {
+ *aUniqueID = reinterpret_cast<uintptr_t>(Intl()->UniqueID());
+ } else if (IntlGeneric()->IsRemote()) {
+ *aUniqueID = IntlGeneric()->AsRemote()->ID();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetDOMNode(nsINode** aDOMNode) {
+ NS_ENSURE_ARG_POINTER(aDOMNode);
+ *aDOMNode = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsINode> node = Intl()->GetNode();
+ node.forget(aDOMNode);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetId(nsAString& aID) {
+ if (!IntlGeneric()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ RemoteAccessible* proxy = IntlGeneric()->AsRemote();
+ if (!proxy) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsString id;
+ proxy->DOMNodeID(id);
+ aID.Assign(id);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetDocument(nsIAccessibleDocument** aDocument) {
+ NS_ENSURE_ARG_POINTER(aDocument);
+ *aDocument = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aDocument = ToXPCDocument(Intl()->Document()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetRootDocument(nsIAccessibleDocument** aRootDocument) {
+ NS_ENSURE_ARG_POINTER(aRootDocument);
+ *aRootDocument = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aRootDocument = ToXPCDocument(Intl()->RootAccessible()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetRole(uint32_t* aRole) {
+ NS_ENSURE_ARG_POINTER(aRole);
+ *aRole = nsIAccessibleRole::ROLE_NOTHING;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ *aRole = IntlGeneric()->Role();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetState(uint32_t* aState, uint32_t* aExtraState) {
+ NS_ENSURE_ARG_POINTER(aState);
+
+ Accessible* acc = IntlGeneric();
+ if (acc) {
+ nsAccUtils::To32States(acc->State(), aState, aExtraState);
+ } else {
+ nsAccUtils::To32States(states::DEFUNCT, aState, aExtraState);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetName(nsAString& aName) {
+ aName.Truncate();
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ nsAutoString name;
+ IntlGeneric()->Name(name);
+
+ aName.Assign(name);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetDescription(nsAString& aDescription) {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ nsAutoString desc;
+ IntlGeneric()->Description(desc);
+
+ aDescription.Assign(desc);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetLanguage(nsAString& aLanguage) {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ nsAutoString lang;
+ IntlGeneric()->Language(lang);
+
+ aLanguage.Assign(lang);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetValue(nsAString& aValue) {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ nsAutoString value;
+ IntlGeneric()->Value(value);
+
+ aValue.Assign(value);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetAccessKey(nsAString& aAccessKey) {
+ aAccessKey.Truncate();
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ IntlGeneric()->AccessKey().ToString(aAccessKey);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetKeyboardShortcut(nsAString& aKeyBinding) {
+ aKeyBinding.Truncate();
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ if (IntlGeneric()->IsRemote()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+ Intl()->KeyboardShortcut().ToString(aKeyBinding);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetAttributes(nsIPersistentProperties** aAttributes) {
+ NS_ENSURE_ARG_POINTER(aAttributes);
+ *aAttributes = nullptr;
+
+ if (!IntlGeneric()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ RefPtr<nsPersistentProperties> props = new nsPersistentProperties();
+
+ RefPtr<AccAttributes> attributes = IntlGeneric()->Attributes();
+
+ nsAutoString unused;
+ for (auto iter : *attributes) {
+ nsAutoString name;
+ iter.NameAsString(name);
+
+ nsAutoString value;
+ iter.ValueAsString(value);
+
+ props->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused);
+ }
+
+ props.forget(aAttributes);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetCache(nsIPersistentProperties** aCachedFields) {
+ NS_ENSURE_ARG_POINTER(aCachedFields);
+ *aCachedFields = nullptr;
+
+ if (!IntlGeneric()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ RefPtr<nsPersistentProperties> props = new nsPersistentProperties();
+ if (RemoteAccessible* remoteAcc = IntlGeneric()->AsRemote()) {
+ if (RefPtr<AccAttributes> cachedFields = remoteAcc->mCachedFields) {
+ nsAutoString unused;
+ for (auto iter : *cachedFields) {
+ nsAutoString name;
+ iter.NameAsString(name);
+
+ nsAutoString value;
+ iter.ValueAsString(value);
+
+ props->SetStringProperty(NS_ConvertUTF16toUTF8(name), value, unused);
+ }
+ }
+ }
+
+ props.forget(aCachedFields);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetNativeInterface(nsISupports** aNativeInterface) {
+#ifdef MOZ_WIDGET_COCOA
+ NS_ENSURE_ARG_POINTER(aNativeInterface);
+
+ // We don't cache or store this instance anywhere so each get returns a
+ // different instance. So `acc.nativeInterface != acc.nativeInterface`. This
+ // just seems simpler and more robust for now.
+ nsCOMPtr<nsISupports> macIface = static_cast<nsIAccessibleMacInterface*>(
+ new xpcAccessibleMacInterface(IntlGeneric()));
+ macIface.swap(*aNativeInterface);
+
+ return NS_OK;
+#else
+ return NS_ERROR_NOT_IMPLEMENTED;
+#endif
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetBounds(int32_t* aX, int32_t* aY, int32_t* aWidth,
+ int32_t* aHeight) {
+ NS_ENSURE_ARG_POINTER(aX);
+ *aX = 0;
+ NS_ENSURE_ARG_POINTER(aY);
+ *aY = 0;
+ NS_ENSURE_ARG_POINTER(aWidth);
+ *aWidth = 0;
+ NS_ENSURE_ARG_POINTER(aHeight);
+ *aHeight = 0;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ LayoutDeviceIntRect rect = IntlGeneric()->Bounds();
+ rect.GetRect(aX, aY, aWidth, aHeight);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetBoundsInCSSPixels(int32_t* aX, int32_t* aY, int32_t* aWidth,
+ int32_t* aHeight) {
+ NS_ENSURE_ARG_POINTER(aX);
+ *aX = 0;
+ NS_ENSURE_ARG_POINTER(aY);
+ *aY = 0;
+ NS_ENSURE_ARG_POINTER(aWidth);
+ *aWidth = 0;
+ NS_ENSURE_ARG_POINTER(aHeight);
+ *aHeight = 0;
+
+ if (!IntlGeneric()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsIntRect rect = IntlGeneric()->BoundsInCSSPixels();
+ rect.GetRect(aX, aY, aWidth, aHeight);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GroupPosition(int32_t* aGroupLevel,
+ int32_t* aSimilarItemsInGroup,
+ int32_t* aPositionInGroup) {
+ NS_ENSURE_ARG_POINTER(aGroupLevel);
+ NS_ENSURE_ARG_POINTER(aSimilarItemsInGroup);
+ NS_ENSURE_ARG_POINTER(aPositionInGroup);
+
+ GroupPos groupPos = IntlGeneric()->GroupPosition();
+
+ *aGroupLevel = groupPos.level;
+ *aSimilarItemsInGroup = groupPos.setSize;
+ *aPositionInGroup = groupPos.posInSet;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetRelationByType(uint32_t aType,
+ nsIAccessibleRelation** aRelation) {
+ NS_ENSURE_ARG_POINTER(aRelation);
+ *aRelation = nullptr;
+
+ NS_ENSURE_ARG(aType <= static_cast<uint32_t>(RelationType::LAST));
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ Relation rel =
+ IntlGeneric()->RelationByType(static_cast<RelationType>(aType));
+ NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &rel));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetRelations(nsIArray** aRelations) {
+ NS_ENSURE_ARG_POINTER(aRelations);
+ *aRelations = nullptr;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIMutableArray> relations = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ NS_ENSURE_TRUE(relations, NS_ERROR_OUT_OF_MEMORY);
+
+ for (uint32_t type = 0; type <= static_cast<uint32_t>(RelationType::LAST);
+ ++type) {
+ nsCOMPtr<nsIAccessibleRelation> relation;
+ nsresult rv = GetRelationByType(type, getter_AddRefs(relation));
+
+ if (NS_SUCCEEDED(rv) && relation) {
+ uint32_t targets = 0;
+ relation->GetTargetsCount(&targets);
+ if (targets) relations->AppendElement(relation);
+ }
+ }
+
+ NS_ADDREF(*aRelations = relations);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetFocusedChild(nsIAccessible** aChild) {
+ NS_ENSURE_ARG_POINTER(aChild);
+ *aChild = nullptr;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aChild = ToXPC(IntlGeneric()->FocusedChild()));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetChildAtPoint(int32_t aX, int32_t aY,
+ nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(IntlGeneric()->ChildAtPoint(
+ aX, aY, Accessible::EWhichChildAtPoint::DirectChild)));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetDeepestChildAtPoint(int32_t aX, int32_t aY,
+ nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(IntlGeneric()->ChildAtPoint(
+ aX, aY, Accessible::EWhichChildAtPoint::DeepestChild)));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetDeepestChildAtPointInProcess(int32_t aX, int32_t aY,
+ nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+
+ Accessible* generic = IntlGeneric();
+ if (!generic || generic->IsRemote()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(Intl()->LocalChildAtPoint(
+ aX, aY, Accessible::EWhichChildAtPoint::DeepestChild)));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::SetSelected(bool aSelect) {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ IntlGeneric()->SetSelected(aSelect);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::TakeSelection() {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ IntlGeneric()->TakeSelection();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::TakeFocus() {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ IntlGeneric()->TakeFocus();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetActionCount(uint8_t* aActionCount) {
+ NS_ENSURE_ARG_POINTER(aActionCount);
+ *aActionCount = 0;
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ *aActionCount = IntlGeneric()->ActionCount();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetActionName(uint8_t aIndex, nsAString& aName) {
+ aName.Truncate();
+
+ if (!IntlGeneric()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (aIndex >= IntlGeneric()->ActionCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsAutoString name;
+ IntlGeneric()->ActionNameAt(aIndex, name);
+
+ aName.Assign(name);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetActionDescription(uint8_t aIndex, nsAString& aDescription) {
+ aDescription.Truncate();
+
+ if (!IntlGeneric()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (aIndex >= IntlGeneric()->ActionCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsAutoString description;
+ IntlGeneric()->ActionDescriptionAt(aIndex, description);
+
+ aDescription.Assign(description);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::DoAction(uint8_t aIndex) {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ return IntlGeneric()->DoAction(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+xpcAccessible::ScrollTo(uint32_t aHow) {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ IntlGeneric()->ScrollTo(aHow);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY) {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ IntlGeneric()->ScrollToPoint(aCoordinateType, aX, aY);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::Announce(const nsAString& aAnnouncement, uint16_t aPriority) {
+ if (RemoteAccessible* proxy = IntlGeneric()->AsRemote()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsString announcement(aAnnouncement);
+ proxy->Announce(announcement, aPriority);
+#endif
+ } else {
+ Intl()->Announce(aAnnouncement, aPriority);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetComputedARIARole(nsAString& aRole) {
+ if (!IntlGeneric()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsStaticAtom* ariaRole = IntlGeneric()->ComputedARIARole();
+ if (ariaRole) {
+ ariaRole->ToString(aRole);
+ }
+
+ return NS_OK;
+}