summaryrefslogtreecommitdiffstats
path: root/accessible/xpcom
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/xpcom')
-rwxr-xr-xaccessible/xpcom/AccEventGen.py256
-rw-r--r--accessible/xpcom/AccEvents.conf21
-rw-r--r--accessible/xpcom/moz.build79
-rw-r--r--accessible/xpcom/nsAccessibleRelation.cpp60
-rw-r--r--accessible/xpcom/nsAccessibleRelation.h46
-rw-r--r--accessible/xpcom/xpcAccessibilityService.cpp295
-rw-r--r--accessible/xpcom/xpcAccessibilityService.h68
-rw-r--r--accessible/xpcom/xpcAccessible.cpp768
-rw-r--r--accessible/xpcom/xpcAccessible.h111
-rw-r--r--accessible/xpcom/xpcAccessibleApplication.cpp60
-rw-r--r--accessible/xpcom/xpcAccessibleApplication.h47
-rw-r--r--accessible/xpcom/xpcAccessibleDocument.cpp191
-rw-r--r--accessible/xpcom/xpcAccessibleDocument.h138
-rw-r--r--accessible/xpcom/xpcAccessibleGeneric.cpp61
-rw-r--r--accessible/xpcom/xpcAccessibleGeneric.h96
-rw-r--r--accessible/xpcom/xpcAccessibleHyperLink.cpp154
-rw-r--r--accessible/xpcom/xpcAccessibleHyperLink.h48
-rw-r--r--accessible/xpcom/xpcAccessibleHyperText.cpp703
-rw-r--r--accessible/xpcom/xpcAccessibleHyperText.h57
-rw-r--r--accessible/xpcom/xpcAccessibleImage.cpp51
-rw-r--r--accessible/xpcom/xpcAccessibleImage.h40
-rw-r--r--accessible/xpcom/xpcAccessibleMacInterface.h104
-rw-r--r--accessible/xpcom/xpcAccessibleMacInterface.mm539
-rw-r--r--accessible/xpcom/xpcAccessibleSelectable.cpp121
-rw-r--r--accessible/xpcom/xpcAccessibleSelectable.h50
-rw-r--r--accessible/xpcom/xpcAccessibleTable.cpp411
-rw-r--r--accessible/xpcom/xpcAccessibleTable.h78
-rw-r--r--accessible/xpcom/xpcAccessibleTableCell.cpp141
-rw-r--r--accessible/xpcom/xpcAccessibleTableCell.h52
-rw-r--r--accessible/xpcom/xpcAccessibleTextRange.cpp159
-rw-r--r--accessible/xpcom/xpcAccessibleTextRange.h81
-rw-r--r--accessible/xpcom/xpcAccessibleValue.cpp101
-rw-r--r--accessible/xpcom/xpcAccessibleValue.h42
33 files changed, 5229 insertions, 0 deletions
diff --git a/accessible/xpcom/AccEventGen.py b/accessible/xpcom/AccEventGen.py
new file mode 100755
index 0000000000..791b57827d
--- /dev/null
+++ b/accessible/xpcom/AccEventGen.py
@@ -0,0 +1,256 @@
+#!/usr/bin/env python
+#
+# 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/.
+
+import os
+
+import buildconfig
+import mozpack.path as mozpath
+from xpidl import xpidl
+
+# Load the webidl configuration file.
+glbl = {}
+exec(
+ open(
+ mozpath.join(buildconfig.topsrcdir, "dom", "bindings", "Bindings.conf")
+ ).read(),
+ glbl,
+)
+webidlconfig = glbl["DOMInterfaces"]
+
+# Instantiate the parser.
+p = xpidl.IDLParser()
+
+
+def findIDL(includePath, interfaceFileName):
+ for d in includePath:
+ path = mozpath.join(d, interfaceFileName)
+ if os.path.exists(path):
+ return path
+ raise BaseException(
+ "No IDL file found for interface %s "
+ "in include path %r" % (interfaceFileName, includePath)
+ )
+
+
+def loadEventIDL(parser, includePath, eventname):
+ eventidl = "nsIAccessible%s.idl" % eventname
+ idlFile = findIDL(includePath, eventidl)
+ idl = p.parse(open(idlFile).read(), idlFile)
+ idl.resolve(includePath, p, webidlconfig)
+ return idl, idlFile
+
+
+class Configuration:
+ def __init__(self, filename):
+ config = {}
+ exec(open(filename).read(), config)
+ self.simple_events = config.get("simple_events", [])
+
+
+def firstCap(str):
+ return str[0].upper() + str[1:]
+
+
+def writeAttributeParams(a):
+ return "%s a%s" % (a.realtype.nativeType("in"), firstCap(a.name))
+
+
+def print_header_file(fd, conf, incdirs):
+ idl_paths = set()
+
+ fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n")
+ fd.write(
+ "#ifndef _mozilla_a11y_generated_AccEvents_h_\n"
+ "#define _mozilla_a11y_generated_AccEvents_h_\n\n"
+ )
+ fd.write('#include "nscore.h"\n')
+ fd.write('#include "nsCOMPtr.h"\n')
+ fd.write('#include "nsCycleCollectionParticipant.h"\n')
+ fd.write('#include "nsString.h"\n')
+ for e in conf.simple_events:
+ fd.write('#include "nsIAccessible%s.h"\n' % e)
+ for e in conf.simple_events:
+ idl, idl_path = loadEventIDL(p, incdirs, e)
+ idl_paths.add(idl_path)
+ for iface in filter(lambda p: p.kind == "interface", idl.productions):
+ classname = "xpcAcc%s" % e
+ baseinterfaces = interfaces(iface)
+
+ fd.write("\nclass %s final : public %s\n" % (classname, iface.name))
+ fd.write("{\n")
+ fd.write("public:\n")
+
+ attributes = allAttributes(iface)
+ args = map(writeAttributeParams, attributes)
+ fd.write(" %s(%s) :\n" % (classname, ", ".join(args)))
+
+ initializers = []
+ for a in attributes:
+ initializers.append("m%s(a%s)" % (firstCap(a.name), firstCap(a.name)))
+ fd.write(" %s\n {}\n\n" % ", ".join(initializers))
+ fd.write(" NS_DECL_CYCLE_COLLECTING_ISUPPORTS\n")
+ fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS(%s)\n" % (classname))
+
+ for iface in filter(lambda i: i.name != "nsISupports", baseinterfaces):
+ fd.write(" NS_DECL_%s\n" % iface.name.upper())
+
+ fd.write("\nprivate:\n")
+ fd.write(" ~%s() {}\n\n" % classname)
+ for a in attributes:
+ fd.write(" %s\n" % attributeVariableTypeAndName(a))
+ fd.write("};\n\n")
+
+ fd.write("#endif\n")
+
+ return idl_paths
+
+
+def interfaceAttributeTypes(idl):
+ ifaces = filter(lambda p: p.kind == "interface", idl.productions)
+ attributes = []
+ for i in ifaces:
+ ifaceAttributes = allAttributes(i)
+ attributes.extend(ifaceAttributes)
+ ifaceAttrs = filter(lambda a: a.realtype.nativeType("in").endswith("*"), attributes)
+ return map(lambda a: a.realtype.nativeType("in").strip(" *"), ifaceAttrs)
+
+
+def print_cpp(idl, fd, conf, eventname):
+ for p in idl.productions:
+ if p.kind == "interface":
+ write_cpp(eventname, p, fd)
+
+
+def print_cpp_file(fd, conf, incdirs):
+ idl_paths = set()
+ fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n")
+ fd.write('#include "xpcAccEvents.h"\n')
+
+ includes = []
+ for e in conf.simple_events:
+ if e not in includes:
+ includes.append(("nsIAccessible%s" % e))
+
+ types = []
+ for e in conf.simple_events:
+ idl, idl_path = loadEventIDL(p, incdirs, e)
+ idl_paths.add(idl_path)
+ types.extend(interfaceAttributeTypes(idl))
+
+ for c in types:
+ fd.write('#include "%s.h"\n' % c)
+
+ fd.write("\n")
+ for e in conf.simple_events:
+ idl, idl_path = loadEventIDL(p, incdirs, e)
+ idl_paths.add(idl_path)
+ print_cpp(idl, fd, conf, e)
+
+ return idl_paths
+
+
+def attributeVariableTypeAndName(a):
+ if a.realtype.nativeType("in").endswith("*"):
+ l = [
+ "nsCOMPtr<%s> m%s;"
+ % (a.realtype.nativeType("in").strip("* "), firstCap(a.name))
+ ]
+ elif a.realtype.nativeType("in").count("nsAString"):
+ l = ["nsString m%s;" % firstCap(a.name)]
+ elif a.realtype.nativeType("in").count("nsACString"):
+ l = ["nsCString m%s;" % firstCap(a.name)]
+ else:
+ l = ["%sm%s;" % (a.realtype.nativeType("in"), firstCap(a.name))]
+ return ", ".join(l)
+
+
+def writeAttributeGetter(fd, classname, a):
+ fd.write("NS_IMETHODIMP\n")
+ fd.write("%s::Get%s(" % (classname, firstCap(a.name)))
+ if a.realtype.nativeType("in").endswith("*"):
+ fd.write(
+ "%s** a%s" % (a.realtype.nativeType("in").strip("* "), firstCap(a.name))
+ )
+ elif a.realtype.nativeType("in").count("nsAString"):
+ fd.write("nsAString& a%s" % firstCap(a.name))
+ elif a.realtype.nativeType("in").count("nsACString"):
+ fd.write("nsACString& a%s" % firstCap(a.name))
+ else:
+ fd.write("%s*a%s" % (a.realtype.nativeType("in"), firstCap(a.name)))
+ fd.write(")\n")
+ fd.write("{\n")
+ if a.realtype.nativeType("in").endswith("*"):
+ fd.write(" NS_IF_ADDREF(*a%s = m%s);\n" % (firstCap(a.name), firstCap(a.name)))
+ elif a.realtype.nativeType("in").count("nsAString"):
+ fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
+ elif a.realtype.nativeType("in").count("nsACString"):
+ fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
+ else:
+ fd.write(" *a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name)))
+ fd.write(" return NS_OK;\n")
+ fd.write("}\n\n")
+
+
+def interfaces(iface):
+ interfaces = []
+ while iface.base:
+ interfaces.append(iface)
+ iface = iface.idl.getName(xpidl.TypeId(iface.base), iface.location)
+ interfaces.append(iface)
+ interfaces.reverse()
+ return interfaces
+
+
+def allAttributes(iface):
+ attributes = []
+ for i in interfaces(iface):
+ attrs = filter(lambda m: isinstance(m, xpidl.Attribute), i.members)
+ attributes.extend(attrs)
+
+ return attributes
+
+
+def write_cpp(eventname, iface, fd):
+ classname = "xpcAcc%s" % eventname
+ attributes = allAttributes(iface)
+ ccattributes = filter(
+ lambda m: m.realtype.nativeType("in").endswith("*"), attributes
+ )
+ fd.write("NS_IMPL_CYCLE_COLLECTION(%s" % classname)
+ for c in ccattributes:
+ fd.write(", m%s" % firstCap(c.name))
+ fd.write(")\n\n")
+
+ fd.write("NS_IMPL_CYCLE_COLLECTING_ADDREF(%s)\n" % classname)
+ fd.write("NS_IMPL_CYCLE_COLLECTING_RELEASE(%s)\n\n" % classname)
+
+ fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(%s)\n" % classname)
+ for baseiface in interfaces(iface):
+ fd.write(" NS_INTERFACE_MAP_ENTRY(%s)\n" % baseiface.name)
+ fd.write("NS_INTERFACE_MAP_END\n\n")
+
+ for a in attributes:
+ writeAttributeGetter(fd, classname, a)
+
+
+def get_conf(conf_file):
+ conf = Configuration(conf_file)
+ inc_dir = [
+ mozpath.join(buildconfig.topsrcdir, "accessible", "interfaces"),
+ mozpath.join(buildconfig.topsrcdir, "xpcom", "base"),
+ ]
+ return conf, inc_dir
+
+
+def gen_files(fd, conf_file):
+ deps = set()
+ conf, inc_dir = get_conf(conf_file)
+ deps.update(print_header_file(fd, conf, inc_dir))
+ with open(
+ os.path.join(os.path.dirname(fd.name), "xpcAccEvents.cpp"), "w"
+ ) as cpp_fd:
+ deps.update(print_cpp_file(cpp_fd, conf, inc_dir))
+ return deps
diff --git a/accessible/xpcom/AccEvents.conf b/accessible/xpcom/AccEvents.conf
new file mode 100644
index 0000000000..12d3604cd3
--- /dev/null
+++ b/accessible/xpcom/AccEvents.conf
@@ -0,0 +1,21 @@
+""" -*- Mode: Python -*-
+ 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/.
+
+ The name of the event which real interface should have nsIAccessible-prefix,
+ and should be in nsIAccessible<name>.idl file"""
+
+simple_events = [
+ 'Event',
+ 'StateChangeEvent',
+ 'TextChangeEvent',
+ 'TextSelectionChangeEvent',
+ 'HideEvent',
+ 'CaretMoveEvent',
+ 'ObjectAttributeChangedEvent',
+ 'TableChangeEvent',
+ 'VirtualCursorChangeEvent',
+ 'ScrollingEvent',
+ 'AnnouncementEvent'
+ ]
diff --git a/accessible/xpcom/moz.build b/accessible/xpcom/moz.build
new file mode 100644
index 0000000000..1e7b10e167
--- /dev/null
+++ b/accessible/xpcom/moz.build
@@ -0,0 +1,79 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+UNIFIED_SOURCES += [
+ "nsAccessibleRelation.cpp",
+ "xpcAccessibilityService.cpp",
+ "xpcAccessible.cpp",
+ "xpcAccessibleApplication.cpp",
+ "xpcAccessibleDocument.cpp",
+ "xpcAccessibleGeneric.cpp",
+ "xpcAccessibleHyperLink.cpp",
+ "xpcAccessibleHyperText.cpp",
+ "xpcAccessibleImage.cpp",
+ "xpcAccessibleSelectable.cpp",
+ "xpcAccessibleTable.cpp",
+ "xpcAccessibleTableCell.cpp",
+ "xpcAccessibleTextRange.cpp",
+ "xpcAccessibleValue.cpp",
+]
+
+SOURCES += [
+ "!xpcAccEvents.cpp",
+]
+
+EXPORTS += [
+ "!xpcAccEvents.h",
+ "xpcAccessibilityService.h",
+]
+
+LOCAL_INCLUDES += [
+ "/accessible/base",
+ "/accessible/basetypes",
+ "/accessible/generic",
+]
+
+if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
+ LOCAL_INCLUDES += [
+ "/accessible/atk",
+ ]
+elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
+ LOCAL_INCLUDES += [
+ "/accessible/windows/msaa",
+ ]
+elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
+ LOCAL_INCLUDES += [
+ "/accessible/ipc",
+ "/accessible/ipc/other",
+ "/accessible/mac",
+ ]
+ UNIFIED_SOURCES += ["xpcAccessibleMacInterface.mm"]
+ EXPORTS += [
+ "xpcAccessibleMacInterface.h",
+ ]
+elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "android":
+ LOCAL_INCLUDES += [
+ "/accessible/android",
+ ]
+else:
+ LOCAL_INCLUDES += [
+ "/accessible/other",
+ ]
+
+
+GeneratedFile(
+ "xpcAccEvents.h",
+ "xpcAccEvents.cpp",
+ script="AccEventGen.py",
+ entry_point="gen_files",
+ inputs=[
+ "AccEvents.conf",
+ ],
+)
+
+FINAL_LIBRARY = "xul"
+
+include("/ipc/chromium/chromium-config.mozbuild")
diff --git a/accessible/xpcom/nsAccessibleRelation.cpp b/accessible/xpcom/nsAccessibleRelation.cpp
new file mode 100644
index 0000000000..acbff5c776
--- /dev/null
+++ b/accessible/xpcom/nsAccessibleRelation.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "nsAccessibleRelation.h"
+
+#include "Relation.h"
+#include "LocalAccessible.h"
+#include "xpcAccessibleDocument.h"
+
+#include "nsArrayUtils.h"
+#include "nsComponentManagerUtils.h"
+
+using namespace mozilla::a11y;
+
+nsAccessibleRelation::nsAccessibleRelation(uint32_t aType, Relation* aRel)
+ : mType(aType) {
+ mTargets = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ Accessible* targetAcc = nullptr;
+ while ((targetAcc = aRel->Next())) {
+ mTargets->AppendElement(static_cast<nsIAccessible*>(ToXPC(targetAcc)));
+ }
+}
+
+nsAccessibleRelation::~nsAccessibleRelation() {}
+
+// nsISupports
+NS_IMPL_ISUPPORTS(nsAccessibleRelation, nsIAccessibleRelation)
+
+// nsIAccessibleRelation
+NS_IMETHODIMP
+nsAccessibleRelation::GetRelationType(uint32_t* aType) {
+ NS_ENSURE_ARG_POINTER(aType);
+ *aType = mType;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsAccessibleRelation::GetTargetsCount(uint32_t* aCount) {
+ NS_ENSURE_ARG_POINTER(aCount);
+ *aCount = 0;
+ return mTargets->GetLength(aCount);
+}
+
+NS_IMETHODIMP
+nsAccessibleRelation::GetTarget(uint32_t aIndex, nsIAccessible** aTarget) {
+ NS_ENSURE_ARG_POINTER(aTarget);
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIAccessible> target = do_QueryElementAt(mTargets, aIndex, &rv);
+ target.forget(aTarget);
+ return rv;
+}
+
+NS_IMETHODIMP
+nsAccessibleRelation::GetTargets(nsIArray** aTargets) {
+ NS_ENSURE_ARG_POINTER(aTargets);
+ NS_ADDREF(*aTargets = mTargets);
+ return NS_OK;
+}
diff --git a/accessible/xpcom/nsAccessibleRelation.h b/accessible/xpcom/nsAccessibleRelation.h
new file mode 100644
index 0000000000..f8776951f4
--- /dev/null
+++ b/accessible/xpcom/nsAccessibleRelation.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef _nsAccessibleRelation_H_
+#define _nsAccessibleRelation_H_
+
+#include "nsIAccessibleRelation.h"
+
+#include "nsCOMPtr.h"
+#include "nsTArray.h"
+#include "nsIMutableArray.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/a11y/RemoteAccessible.h"
+
+namespace mozilla {
+namespace a11y {
+
+class Relation;
+
+/**
+ * Class represents an accessible relation.
+ */
+class nsAccessibleRelation final : public nsIAccessibleRelation {
+ public:
+ nsAccessibleRelation(uint32_t aType, Relation* aRel);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIACCESSIBLERELATION
+
+ private:
+ nsAccessibleRelation();
+ ~nsAccessibleRelation();
+
+ nsAccessibleRelation(const nsAccessibleRelation&);
+ nsAccessibleRelation& operator=(const nsAccessibleRelation&);
+
+ uint32_t mType;
+ nsCOMPtr<nsIMutableArray> mTargets;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibilityService.cpp b/accessible/xpcom/xpcAccessibilityService.cpp
new file mode 100644
index 0000000000..5a51945e07
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibilityService.cpp
@@ -0,0 +1,295 @@
+/* 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 "xpcAccessibilityService.h"
+
+#include "mozilla/dom/Document.h"
+
+#include "nsAccessiblePivot.h"
+#include "nsAccessibilityService.h"
+#include "Platform.h"
+#include "xpcAccessibleApplication.h"
+#include "xpcAccessibleDocument.h"
+
+#ifdef A11Y_LOG
+# include "Logging.h"
+#endif
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+using namespace mozilla::dom;
+
+xpcAccessibilityService* xpcAccessibilityService::gXPCAccessibilityService =
+ nullptr;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+void xpcAccessibilityService::ShutdownCallback(nsITimer* aTimer,
+ void* aClosure) {
+ MaybeShutdownAccService(nsAccessibilityService::eXPCOM);
+ xpcAccessibilityService* xpcAccService =
+ reinterpret_cast<xpcAccessibilityService*>(aClosure);
+
+ if (xpcAccService->mShutdownTimer) {
+ xpcAccService->mShutdownTimer->Cancel();
+ xpcAccService->mShutdownTimer = nullptr;
+ }
+}
+
+NS_IMETHODIMP_(MozExternalRefCountType)
+xpcAccessibilityService::AddRef(void) {
+ MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(xpcAccessibilityService)
+ MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
+ if (!nsAutoRefCnt::isThreadSafe) {
+ NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
+ }
+ nsrefcnt count = ++mRefCnt;
+ NS_LOG_ADDREF(this, count, "xpcAccessibilityService", sizeof(*this));
+
+ // We want refcount to be > 1 because one reference is added in the XPCOM
+ // accessibility service getter.
+ if (mRefCnt > 1) {
+ if (mShutdownTimer) {
+ mShutdownTimer->Cancel();
+ mShutdownTimer = nullptr;
+ }
+
+ GetOrCreateAccService(nsAccessibilityService::eXPCOM);
+ }
+
+ return count;
+}
+
+NS_IMETHODIMP_(MozExternalRefCountType)
+xpcAccessibilityService::Release(void) {
+ MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
+
+ if (!nsAutoRefCnt::isThreadSafe) {
+ NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
+ }
+
+ nsrefcnt count = --mRefCnt;
+ NS_LOG_RELEASE(this, count, "xpcAccessibilityService");
+
+ if (count == 0) {
+ if (!nsAutoRefCnt::isThreadSafe) {
+ NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
+ }
+
+ mRefCnt = 1; /* stabilize */
+ delete (this);
+ return 0;
+ }
+
+ // When ref count goes down to 1 (held internally as a static reference),
+ // it means that there are no more external references to the
+ // xpcAccessibilityService and we can attempt to shut down acceessiblity
+ // service.
+ if (count == 1 && !mShutdownTimer) {
+ NS_NewTimerWithFuncCallback(
+ getter_AddRefs(mShutdownTimer), ShutdownCallback, this, 100,
+ nsITimer::TYPE_ONE_SHOT, "xpcAccessibilityService::Release");
+ }
+
+ return count;
+}
+
+NS_IMPL_QUERY_INTERFACE(xpcAccessibilityService, nsIAccessibilityService)
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetApplicationAccessible(
+ nsIAccessible** aAccessibleApplication) {
+ NS_ENSURE_ARG_POINTER(aAccessibleApplication);
+
+ NS_IF_ADDREF(*aAccessibleApplication = XPCApplicationAcc());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetAccessibleFor(nsINode* aNode,
+ nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+ if (!aNode) {
+ return NS_OK;
+ }
+
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ DocAccessible* document = accService->GetDocAccessible(aNode->OwnerDoc());
+ if (document) {
+ NS_IF_ADDREF(*aAccessible = ToXPC(document->GetAccessible(aNode)));
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetAccessibleDescendantFor(
+ nsINode* aNode, nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+ if (!aNode) {
+ return NS_OK;
+ }
+
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ DocAccessible* document = accService->GetDocAccessible(aNode->OwnerDoc());
+ if (document) {
+ NS_IF_ADDREF(*aAccessible =
+ ToXPC(document->GetAccessibleOrDescendant(aNode)));
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetStringRole(aRole, aString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
+ nsISupports** aStringStates) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetStringStates(aState, aExtraState, aStringStates);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringEventType(uint32_t aEventType,
+ nsAString& aString) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetStringEventType(aEventType, aString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringRelationType(uint32_t aRelationType,
+ nsAString& aString) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetStringRelationType(aRelationType, aString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetAccessibleFromCache(nsINode* aNode,
+ nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+ if (!aNode) {
+ return NS_OK;
+ }
+
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ // Search for an accessible in each of our per document accessible object
+ // caches. If we don't find it, and the given node is itself a document, check
+ // our cache of document accessibles (document cache). Note usually shutdown
+ // document accessibles are not stored in the document cache, however an
+ // "unofficially" shutdown document (i.e. not from DocManager) can still
+ // exist in the document cache.
+ LocalAccessible* accessible = accService->FindAccessibleInCache(aNode);
+ if (!accessible && aNode->IsDocument()) {
+ accessible = mozilla::a11y::GetExistingDocAccessible(aNode->AsDocument());
+ }
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(accessible));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::CreateAccessiblePivot(nsIAccessible* aRoot,
+ nsIAccessiblePivot** aPivot) {
+ NS_ENSURE_ARG_POINTER(aPivot);
+ NS_ENSURE_ARG(aRoot);
+ *aPivot = nullptr;
+
+ LocalAccessible* accessibleRoot = aRoot->ToInternalAccessible();
+ NS_ENSURE_TRUE(accessibleRoot, NS_ERROR_INVALID_ARG);
+
+ nsAccessiblePivot* pivot = new nsAccessiblePivot(accessibleRoot);
+ NS_ADDREF(*aPivot = pivot);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::SetLogging(const nsACString& aModules) {
+#ifdef A11Y_LOG
+ logging::Enable(PromiseFlatCString(aModules));
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::IsLogged(const nsAString& aModule, bool* aIsLogged) {
+ NS_ENSURE_ARG_POINTER(aIsLogged);
+ *aIsLogged = false;
+
+#ifdef A11Y_LOG
+ *aIsLogged = logging::IsEnabled(aModule);
+#endif
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetConsumers(nsAString& aString) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetConsumers(aString);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NS_GetAccessibilityService
+////////////////////////////////////////////////////////////////////////////////
+
+nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult) {
+ NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
+ *aResult = nullptr;
+
+ if (!GetOrCreateAccService(nsAccessibilityService::eXPCOM)) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ xpcAccessibilityService* service = new xpcAccessibilityService();
+ xpcAccessibilityService::gXPCAccessibilityService = service;
+ NS_ADDREF(*aResult = service);
+
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibilityService.h b/accessible/xpcom/xpcAccessibilityService.h
new file mode 100644
index 0000000000..04c23e7075
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibilityService.h
@@ -0,0 +1,68 @@
+/* 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibilityService_h_
+#define mozilla_a11y_xpcAccessibilityService_h_
+
+#include "nsIAccessibilityService.h"
+#include "nsITimer.h"
+
+class xpcAccessibilityService : public nsIAccessibilityService {
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIACCESSIBILITYSERVICE
+
+ /**
+ * Return true if xpc accessibility service is in use.
+ */
+ static bool IsInUse() {
+ // When ref count goes down to 1 (held internally as a static reference),
+ // it means that there are no more external references and thus it is not in
+ // use.
+ return gXPCAccessibilityService ? gXPCAccessibilityService->mRefCnt > 1
+ : false;
+ }
+
+ protected:
+ virtual ~xpcAccessibilityService() {
+ if (mShutdownTimer) {
+ mShutdownTimer->Cancel();
+ mShutdownTimer = nullptr;
+ }
+ gXPCAccessibilityService = nullptr;
+ }
+
+ private:
+ // xpcAccessibilityService creation is controlled by friend
+ // NS_GetAccessibilityService, keep constructor private.
+ xpcAccessibilityService() = default;
+
+ nsCOMPtr<nsITimer> mShutdownTimer;
+
+ /**
+ * Reference for xpc accessibility service instance.
+ */
+ static xpcAccessibilityService* gXPCAccessibilityService;
+
+ /**
+ * Used to shutdown nsAccessibilityService if xpcom accessible service is not
+ * in use any more.
+ */
+ static void ShutdownCallback(nsITimer* aTimer, void* aClosure);
+
+ friend nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult);
+};
+
+// for component registration
+// {3b265b69-f813-48ff-880d-d88d101af404}
+#define NS_ACCESSIBILITY_SERVICE_CID \
+ { \
+ 0x3b265b69, 0xf813, 0x48ff, { \
+ 0x88, 0x0d, 0xd8, 0x8d, 0x10, 0x1a, 0xf4, 0x04 \
+ } \
+ }
+
+extern nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult);
+
+#endif
diff --git a/accessible/xpcom/xpcAccessible.cpp b/accessible/xpcom/xpcAccessible.cpp
new file mode 100644
index 0000000000..f1c65932c5
--- /dev/null
+++ b/accessible/xpcom/xpcAccessible.cpp
@@ -0,0 +1,768 @@
+/* -*- 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 "LocalAccessible-inl.h"
+#include "mozilla/a11y/DocAccessibleParent.h"
+#include "mozilla/StaticPrefs_accessibility.h"
+#include "AccAttributes.h"
+#include "nsAccUtils.h"
+#include "nsComponentManagerUtils.h"
+#include "nsIAccessibleRelation.h"
+#include "nsIAccessibleRole.h"
+#include "nsAccessibleRelation.h"
+#include "Relation.h"
+#include "Role.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;
+ if (RemoteAccessible* proxy = IntlGeneric()->AsRemote()) {
+ proxy->Language(lang);
+ } else {
+ Intl()->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::GetHelp(nsAString& aHelp) {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+ nsAutoString help;
+ if (RemoteAccessible* proxy = IntlGeneric()->AsRemote()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ proxy->Help(help);
+#endif
+ } else {
+ Intl()->Help(help);
+ }
+
+ aHelp.Assign(help);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetAccessKey(nsAString& aAccessKey) {
+ aAccessKey.Truncate();
+
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (IntlGeneric()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ 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);
+
+#if defined(XP_WIN)
+ if (IntlGeneric()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ *aGroupLevel = 0;
+ *aSimilarItemsInGroup = 0;
+ *aPositionInGroup = 0;
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ 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);
+
+ static const uint32_t relationTypes[] = {
+ nsIAccessibleRelation::RELATION_LABELLED_BY,
+ nsIAccessibleRelation::RELATION_LABEL_FOR,
+ nsIAccessibleRelation::RELATION_DESCRIBED_BY,
+ nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
+ nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
+ nsIAccessibleRelation::RELATION_NODE_PARENT_OF,
+ nsIAccessibleRelation::RELATION_CONTROLLED_BY,
+ nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
+ nsIAccessibleRelation::RELATION_FLOWS_TO,
+ nsIAccessibleRelation::RELATION_FLOWS_FROM,
+ nsIAccessibleRelation::RELATION_MEMBER_OF,
+ nsIAccessibleRelation::RELATION_SUBWINDOW_OF,
+ nsIAccessibleRelation::RELATION_EMBEDS,
+ nsIAccessibleRelation::RELATION_EMBEDDED_BY,
+ nsIAccessibleRelation::RELATION_POPUP_FOR,
+ nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF,
+ nsIAccessibleRelation::RELATION_DEFAULT_BUTTON,
+ nsIAccessibleRelation::RELATION_CONTAINING_DOCUMENT,
+ nsIAccessibleRelation::RELATION_CONTAINING_TAB_PANE,
+ nsIAccessibleRelation::RELATION_CONTAINING_APPLICATION};
+
+ for (uint32_t idx = 0; idx < ArrayLength(relationTypes); idx++) {
+ nsCOMPtr<nsIAccessibleRelation> relation;
+ nsresult rv =
+ GetRelationByType(relationTypes[idx], 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;
+
+#if defined(XP_WIN)
+ if (IntlGeneric()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ IntlGeneric()->SetSelected(aSelect);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::TakeSelection() {
+ if (!IntlGeneric()) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (IntlGeneric()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ 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;
+
+#if defined(XP_WIN)
+ if (IntlGeneric()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ *aActionCount = IntlGeneric()->ActionCount();
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetActionName(uint8_t aIndex, nsAString& aName) {
+#if defined(XP_WIN)
+ if (IntlGeneric()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ 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) {
+#if defined(XP_WIN)
+ if (IntlGeneric()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ 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;
+
+#if defined(XP_WIN)
+ if (IntlGeneric()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ 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;
+
+ if (RemoteAccessible* proxy = IntlGeneric()->AsRemote()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ proxy->ScrollToPoint(aCoordinateType, aX, aY);
+#endif
+ } else {
+ Intl()->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;
+}
diff --git a/accessible/xpcom/xpcAccessible.h b/accessible/xpcom/xpcAccessible.h
new file mode 100644
index 0000000000..a8475020da
--- /dev/null
+++ b/accessible/xpcom/xpcAccessible.h
@@ -0,0 +1,111 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessible_h_
+#define mozilla_a11y_xpcAccessible_h_
+
+#include "nsIAccessible.h"
+
+class nsIAccessible;
+
+namespace mozilla {
+namespace a11y {
+
+class Accessible;
+class LocalAccessible;
+
+/**
+ * XPCOM nsIAccessible interface implementation, used by xpcAccessibleGeneric
+ * class.
+ */
+class xpcAccessible : public nsIAccessible {
+ public:
+ // nsIAccessible
+ NS_IMETHOD GetParent(nsIAccessible** aParent) final;
+ NS_IMETHOD GetNextSibling(nsIAccessible** aNextSibling) final;
+ NS_IMETHOD GetPreviousSibling(nsIAccessible** aPreviousSibling) final;
+ NS_IMETHOD GetFirstChild(nsIAccessible** aFirstChild) final;
+ NS_IMETHOD GetLastChild(nsIAccessible** aLastChild) final;
+ NS_IMETHOD GetChildCount(int32_t* aChildCount) final;
+ NS_IMETHOD GetChildAt(int32_t aChildIndex, nsIAccessible** aChild) final;
+ NS_IMETHOD GetChildren(nsIArray** aChildren) final;
+ NS_IMETHOD GetIndexInParent(int32_t* aIndexInParent) final;
+
+ NS_IMETHOD GetUniqueID(int64_t* aUniqueID) final;
+ NS_IMETHOD GetDOMNode(nsINode** aDOMNode) final;
+ NS_IMETHOD GetId(nsAString& aID) final;
+ NS_IMETHOD GetDocument(nsIAccessibleDocument** aDocument) final;
+ NS_IMETHOD GetRootDocument(nsIAccessibleDocument** aRootDocument) final;
+
+ NS_IMETHOD GetRole(uint32_t* aRole) final;
+ NS_IMETHOD GetState(uint32_t* aState, uint32_t* aExtraState) final;
+
+ NS_IMETHOD GetDescription(nsAString& aDescription) final;
+ NS_IMETHOD GetName(nsAString& aName) final;
+ NS_IMETHOD GetLanguage(nsAString& aLanguage) final;
+ NS_IMETHOD GetValue(nsAString& aValue) final;
+ NS_IMETHOD GetHelp(nsAString& aHelp) final;
+
+ NS_IMETHOD GetAccessKey(nsAString& aAccessKey) final;
+ NS_IMETHOD GetKeyboardShortcut(nsAString& aKeyBinding) final;
+
+ NS_IMETHOD GetAttributes(nsIPersistentProperties** aAttributes) final;
+
+ NS_IMETHOD GetCache(nsIPersistentProperties** aCachedFields) final;
+
+ NS_IMETHOD GetNativeInterface(nsISupports** aNativeInterface) final;
+
+ NS_IMETHOD GetBounds(int32_t* aX, int32_t* aY, int32_t* aWidth,
+ int32_t* aHeight) final;
+ NS_IMETHOD GetBoundsInCSSPixels(int32_t* aX, int32_t* aY, int32_t* aWidth,
+ int32_t* aHeight) final;
+ NS_IMETHOD GroupPosition(int32_t* aGroupLevel, int32_t* aSimilarItemsInGroup,
+ int32_t* aPositionInGroup) final;
+ NS_IMETHOD GetRelationByType(uint32_t aType,
+ nsIAccessibleRelation** aRelation) final;
+ NS_IMETHOD GetRelations(nsIArray** aRelations) final;
+
+ NS_IMETHOD GetFocusedChild(nsIAccessible** aChild) final;
+ NS_IMETHOD GetChildAtPoint(int32_t aX, int32_t aY,
+ nsIAccessible** aAccessible) final;
+ NS_IMETHOD GetDeepestChildAtPoint(int32_t aX, int32_t aY,
+ nsIAccessible** aAccessible) final;
+ NS_IMETHOD GetDeepestChildAtPointInProcess(int32_t aX, int32_t aY,
+ nsIAccessible** aAccessible) final;
+
+ NS_IMETHOD SetSelected(bool aSelect) final;
+ NS_IMETHOD TakeSelection() final;
+ NS_IMETHOD TakeFocus() final;
+
+ NS_IMETHOD GetActionCount(uint8_t* aActionCount) final;
+ NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName) final;
+ NS_IMETHOD GetActionDescription(uint8_t aIndex,
+ nsAString& aDescription) final;
+ NS_IMETHOD DoAction(uint8_t aIndex) final;
+
+ MOZ_CAN_RUN_SCRIPT
+ NS_IMETHOD ScrollTo(uint32_t aHow) final;
+ NS_IMETHOD ScrollToPoint(uint32_t aCoordinateType, int32_t aX,
+ int32_t aY) final;
+
+ NS_IMETHOD Announce(const nsAString& aAnnouncement, uint16_t aPriority) final;
+
+ protected:
+ xpcAccessible() {}
+ virtual ~xpcAccessible() {}
+
+ private:
+ LocalAccessible* Intl();
+ Accessible* IntlGeneric();
+
+ xpcAccessible(const xpcAccessible&) = delete;
+ xpcAccessible& operator=(const xpcAccessible&) = delete;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleApplication.cpp b/accessible/xpcom/xpcAccessibleApplication.cpp
new file mode 100644
index 0000000000..133c255778
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleApplication.cpp
@@ -0,0 +1,60 @@
+/* -*- 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 "xpcAccessibleApplication.h"
+
+#include "ApplicationAccessible.h"
+
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+NS_IMPL_ISUPPORTS_INHERITED(xpcAccessibleApplication, xpcAccessibleGeneric,
+ nsIAccessibleApplication)
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleApplication
+
+NS_IMETHODIMP
+xpcAccessibleApplication::GetAppName(nsAString& aName) {
+ aName.Truncate();
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->AppName(aName);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleApplication::GetAppVersion(nsAString& aVersion) {
+ aVersion.Truncate();
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->AppVersion(aVersion);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleApplication::GetPlatformName(nsAString& aName) {
+ aName.Truncate();
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->PlatformName(aName);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleApplication::GetPlatformVersion(nsAString& aVersion) {
+ aVersion.Truncate();
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->PlatformVersion(aVersion);
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleApplication.h b/accessible/xpcom/xpcAccessibleApplication.h
new file mode 100644
index 0000000000..432d0a07bb
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleApplication.h
@@ -0,0 +1,47 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleApplication_h_
+#define mozilla_a11y_xpcAccessibleApplication_h_
+
+#include "nsIAccessibleApplication.h"
+#include "ApplicationAccessible.h"
+#include "xpcAccessibleGeneric.h"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * XPCOM wrapper around ApplicationAccessible class.
+ */
+class xpcAccessibleApplication : public xpcAccessibleGeneric,
+ public nsIAccessibleApplication {
+ public:
+ explicit xpcAccessibleApplication(Accessible* aIntl)
+ : xpcAccessibleGeneric(aIntl) {}
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIAccessibleApplication
+ NS_IMETHOD GetAppName(nsAString& aName) final;
+ NS_IMETHOD GetAppVersion(nsAString& aVersion) final;
+ NS_IMETHOD GetPlatformName(nsAString& aName) final;
+ NS_IMETHOD GetPlatformVersion(nsAString& aVersion) final;
+
+ protected:
+ virtual ~xpcAccessibleApplication() { Shutdown(); }
+
+ private:
+ ApplicationAccessible* Intl() { return mIntl->AsLocal()->AsApplication(); }
+
+ xpcAccessibleApplication(const xpcAccessibleApplication&) = delete;
+ xpcAccessibleApplication& operator=(const xpcAccessibleApplication&) = delete;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleDocument.cpp b/accessible/xpcom/xpcAccessibleDocument.cpp
new file mode 100644
index 0000000000..1ddd5c8372
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleDocument.cpp
@@ -0,0 +1,191 @@
+/* -*- 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 "xpcAccessibleDocument.h"
+#include "xpcAccessibleImage.h"
+#include "xpcAccessibleTable.h"
+#include "xpcAccessibleTableCell.h"
+
+#include "mozilla/a11y/DocAccessibleParent.h"
+#include "nsAccUtils.h"
+#include "DocAccessible-inl.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+NS_IMPL_QUERY_INTERFACE_INHERITED(xpcAccessibleDocument, xpcAccessibleHyperText,
+ nsIAccessibleDocument)
+NS_IMPL_ADDREF_INHERITED(xpcAccessibleDocument, xpcAccessibleHyperText)
+NS_IMETHODIMP_(MozExternalRefCountType) xpcAccessibleDocument::Release(void) {
+ nsrefcnt r = xpcAccessibleHyperText::Release();
+ NS_LOG_RELEASE(this, r, "xpcAccessibleDocument");
+
+ // The only reference to the xpcAccessibleDocument is in DocManager's cache.
+ if (r == 1 && !!mIntl && mCache.Count() == 0) {
+ if (mIntl->IsLocal()) {
+ GetAccService()->RemoveFromXPCDocumentCache(mIntl->AsLocal()->AsDoc());
+ } else {
+ GetAccService()->RemoveFromRemoteXPCDocumentCache(
+ mIntl->AsRemote()->AsDoc());
+ }
+ }
+ return r;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleDocument
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetURL(nsAString& aURL) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ nsAccUtils::DocumentURL(mIntl, aURL);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetTitle(nsAString& aTitle) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ nsAutoString title;
+ Intl()->Title(title);
+ aTitle = title;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetMimeType(nsAString& aType) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->MimeType(aType);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetDocType(nsAString& aType) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->DocType(aType);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetDOMDocument(dom::Document** aDOMDocument) {
+ NS_ENSURE_ARG_POINTER(aDOMDocument);
+ *aDOMDocument = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (Intl()->DocumentNode()) NS_ADDREF(*aDOMDocument = Intl()->DocumentNode());
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetWindow(mozIDOMWindowProxy** aDOMWindow) {
+ NS_ENSURE_ARG_POINTER(aDOMWindow);
+ *aDOMWindow = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aDOMWindow = Intl()->DocumentNode()->GetWindow());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetParentDocument(nsIAccessibleDocument** aDocument) {
+ NS_ENSURE_ARG_POINTER(aDocument);
+ *aDocument = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aDocument = ToXPCDocument(Intl()->ParentDocument()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetChildDocumentCount(uint32_t* aCount) {
+ NS_ENSURE_ARG_POINTER(aCount);
+ *aCount = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aCount = Intl()->ChildDocumentCount();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetChildDocumentAt(uint32_t aIndex,
+ nsIAccessibleDocument** aDocument) {
+ NS_ENSURE_ARG_POINTER(aDocument);
+ *aDocument = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aDocument = ToXPCDocument(Intl()->GetChildDocumentAt(aIndex)));
+ return *aDocument ? NS_OK : NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor) {
+ NS_ENSURE_ARG_POINTER(aVirtualCursor);
+ *aVirtualCursor = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ NS_ADDREF(*aVirtualCursor = Intl()->VirtualCursor());
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// xpcAccessibleDocument
+
+xpcAccessibleGeneric* xpcAccessibleDocument::GetAccessible(
+ Accessible* aAccessible) {
+ if (aAccessible->IsLocal() &&
+ ToXPCDocument(aAccessible->AsLocal()->Document()) != this) {
+ NS_ERROR(
+ "This XPCOM document is not related with given internal accessible!");
+ return nullptr;
+ }
+
+ if (aAccessible->IsRemote() &&
+ ToXPCDocument(aAccessible->AsRemote()->Document()) != this) {
+ NS_ERROR(
+ "This XPCOM document is not related with given internal accessible!");
+ return nullptr;
+ }
+
+ if (aAccessible->IsDoc()) return this;
+
+ return mCache.LookupOrInsertWith(aAccessible, [&]() -> xpcAccessibleGeneric* {
+ if (aAccessible->IsImage()) {
+ return new xpcAccessibleImage(aAccessible);
+ }
+ if (aAccessible->IsTable()) {
+ return new xpcAccessibleTable(aAccessible);
+ }
+ if (aAccessible->IsTableCell()) {
+ return new xpcAccessibleTableCell(aAccessible);
+ }
+ if (aAccessible->IsHyperText()) {
+ return new xpcAccessibleHyperText(aAccessible);
+ }
+
+ return new xpcAccessibleGeneric(aAccessible);
+ });
+}
+
+void xpcAccessibleDocument::Shutdown() {
+ for (auto iter = mCache.Iter(); !iter.Done(); iter.Next()) {
+ iter.Data()->Shutdown();
+ iter.Remove();
+ }
+ xpcAccessibleGeneric::Shutdown();
+}
diff --git a/accessible/xpcom/xpcAccessibleDocument.h b/accessible/xpcom/xpcAccessibleDocument.h
new file mode 100644
index 0000000000..416a1c5497
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleDocument.h
@@ -0,0 +1,138 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleDocument_h_
+#define mozilla_a11y_xpcAccessibleDocument_h_
+
+#include "nsIAccessibleDocument.h"
+
+#include "DocAccessible.h"
+#include "nsAccessibilityService.h"
+#include "xpcAccessibleApplication.h"
+#include "xpcAccessibleHyperText.h"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * XPCOM wrapper around DocAccessible class.
+ */
+class xpcAccessibleDocument : public xpcAccessibleHyperText,
+ public nsIAccessibleDocument {
+ public:
+ explicit xpcAccessibleDocument(Accessible* aIntl)
+ : xpcAccessibleHyperText(aIntl),
+ mCache(kDefaultCacheLength),
+ mRemote(aIntl->IsRemote()) {
+ // XXX: Once there is a base doc class that both remote and local
+ // accessibles inherit, we can add the type to the prototype and remove this
+ // assert.
+ MOZ_ASSERT(aIntl->IsDoc());
+ }
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIAccessibleDocument
+ NS_IMETHOD GetURL(nsAString& aURL) final;
+ NS_IMETHOD GetTitle(nsAString& aTitle) final;
+ NS_IMETHOD GetMimeType(nsAString& aType) final;
+ NS_IMETHOD GetDocType(nsAString& aType) final;
+ NS_IMETHOD GetDOMDocument(dom::Document** aDOMDocument) final;
+ NS_IMETHOD GetWindow(mozIDOMWindowProxy** aDOMWindow) final;
+ NS_IMETHOD GetParentDocument(nsIAccessibleDocument** aDocument) final;
+ NS_IMETHOD GetChildDocumentCount(uint32_t* aCount) final;
+ NS_IMETHOD GetChildDocumentAt(uint32_t aIndex,
+ nsIAccessibleDocument** aDocument) final;
+ NS_IMETHOD GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor) final;
+
+ /**
+ * Return XPCOM wrapper for the internal accessible.
+ */
+ xpcAccessibleGeneric* GetAccessible(Accessible* aAccessible);
+
+ virtual void Shutdown() override;
+
+ protected:
+ virtual ~xpcAccessibleDocument() {}
+
+ private:
+ DocAccessible* Intl() {
+ if (LocalAccessible* acc = mIntl->AsLocal()) {
+ return acc->AsDoc();
+ }
+
+ return nullptr;
+ }
+
+ void NotifyOfShutdown(Accessible* aAccessible) {
+ xpcAccessibleGeneric* xpcAcc = mCache.Get(aAccessible);
+ if (xpcAcc) {
+ xpcAcc->Shutdown();
+ }
+
+ mCache.Remove(aAccessible);
+ if (mCache.Count() == 0 && mRefCnt == 1) {
+ if (mIntl->IsLocal()) {
+ GetAccService()->RemoveFromXPCDocumentCache(mIntl->AsLocal()->AsDoc());
+ } else {
+ GetAccService()->RemoveFromRemoteXPCDocumentCache(
+ mIntl->AsRemote()->AsDoc());
+ }
+ }
+ }
+
+ friend class DocManager;
+ friend class DocAccessible;
+ friend class RemoteAccessible;
+ friend class RemoteAccessibleBase<RemoteAccessible>;
+ friend class xpcAccessibleGeneric;
+
+ xpcAccessibleDocument(const xpcAccessibleDocument&) = delete;
+ xpcAccessibleDocument& operator=(const xpcAccessibleDocument&) = delete;
+
+ nsTHashMap<nsPtrHashKey<const void>, xpcAccessibleGeneric*> mCache;
+ bool mRemote;
+};
+
+inline xpcAccessibleGeneric* ToXPC(Accessible* aAccessible) {
+ if (!aAccessible) return nullptr;
+
+ if (aAccessible->IsApplication()) return XPCApplicationAcc();
+
+ xpcAccessibleDocument* xpcDoc =
+ aAccessible->IsLocal()
+ ? GetAccService()->GetXPCDocument(aAccessible->AsLocal()->Document())
+ : GetAccService()->GetXPCDocument(
+ aAccessible->AsRemote()->Document());
+ return xpcDoc ? xpcDoc->GetAccessible(aAccessible) : nullptr;
+}
+
+inline xpcAccessibleHyperText* ToXPCText(Accessible* aAccessible) {
+ if (!aAccessible || !aAccessible->IsHyperText()) {
+ return nullptr;
+ }
+
+ xpcAccessibleDocument* xpcDoc =
+ aAccessible->IsLocal()
+ ? GetAccService()->GetXPCDocument(aAccessible->AsLocal()->Document())
+ : nsAccessibilityService::GetXPCDocument(
+ aAccessible->AsRemote()->Document());
+ return static_cast<xpcAccessibleHyperText*>(
+ xpcDoc ? xpcDoc->GetAccessible(aAccessible) : nullptr);
+}
+
+inline xpcAccessibleDocument* ToXPCDocument(DocAccessible* aAccessible) {
+ return GetAccService()->GetXPCDocument(aAccessible);
+}
+
+inline xpcAccessibleDocument* ToXPCDocument(DocAccessibleParent* aAccessible) {
+ return GetAccService()->GetXPCDocument(aAccessible);
+}
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleGeneric.cpp b/accessible/xpcom/xpcAccessibleGeneric.cpp
new file mode 100644
index 0000000000..aaef5ac14c
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleGeneric.cpp
@@ -0,0 +1,61 @@
+/* -*- 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 "xpcAccessibleGeneric.h"
+
+#include "xpcAccessibleDocument.h"
+
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+NS_INTERFACE_MAP_BEGIN(xpcAccessibleGeneric)
+ NS_INTERFACE_MAP_ENTRY(nsIAccessible)
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleSelectable,
+ mSupportedIfaces & eSelectable)
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleValue,
+ mSupportedIfaces & eValue)
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleHyperLink,
+ mSupportedIfaces & eHyperLink)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessible)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(xpcAccessibleGeneric)
+NS_IMPL_RELEASE(xpcAccessibleGeneric)
+
+xpcAccessibleGeneric::~xpcAccessibleGeneric() {
+ if (!mIntl) {
+ return;
+ }
+
+ xpcAccessibleDocument* xpcDoc = nullptr;
+ if (mIntl->IsLocal()) {
+ LocalAccessible* acc = mIntl->AsLocal();
+ if (!acc->IsDoc() && !acc->IsApplication()) {
+ xpcDoc = GetAccService()->GetXPCDocument(acc->Document());
+ xpcDoc->NotifyOfShutdown(acc);
+ }
+ } else {
+ RemoteAccessible* proxy = mIntl->AsRemote();
+ if (!proxy->IsDoc()) {
+ xpcDoc = GetAccService()->GetXPCDocument(proxy->Document());
+ xpcDoc->NotifyOfShutdown(proxy);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessible
+
+LocalAccessible* xpcAccessibleGeneric::ToInternalAccessible() {
+ return mIntl->AsLocal();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// xpcAccessibleGeneric
+
+void xpcAccessibleGeneric::Shutdown() { mIntl = nullptr; }
diff --git a/accessible/xpcom/xpcAccessibleGeneric.h b/accessible/xpcom/xpcAccessibleGeneric.h
new file mode 100644
index 0000000000..65df7e6ec7
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleGeneric.h
@@ -0,0 +1,96 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleGeneric_h_
+#define mozilla_a11y_xpcAccessibleGeneric_h_
+
+#include "xpcAccessible.h"
+#include "xpcAccessibleHyperLink.h"
+#include "xpcAccessibleSelectable.h"
+#include "xpcAccessibleValue.h"
+
+#include "LocalAccessible.h"
+#include "mozilla/a11y/Accessible.h"
+#include "mozilla/a11y/RemoteAccessible.h"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * XPCOM wrapper around Accessible class.
+ */
+class xpcAccessibleGeneric : public xpcAccessible,
+ public xpcAccessibleHyperLink,
+ public xpcAccessibleSelectable,
+ public xpcAccessibleValue {
+ public:
+ explicit xpcAccessibleGeneric(Accessible* aInternal)
+ : mIntl(aInternal), mSupportedIfaces(0) {
+ if (aInternal->IsSelect()) mSupportedIfaces |= eSelectable;
+ if (aInternal->HasNumericValue()) mSupportedIfaces |= eValue;
+ if (aInternal->IsLink()) mSupportedIfaces |= eHyperLink;
+ }
+
+ NS_DECL_ISUPPORTS
+
+ // nsIAccessible
+ LocalAccessible* ToInternalAccessible() final;
+ Accessible* ToInternalGeneric() final { return mIntl; }
+
+ // xpcAccessibleGeneric
+ virtual void Shutdown();
+
+ protected:
+ virtual ~xpcAccessibleGeneric();
+
+ Accessible* mIntl;
+
+ enum {
+ eSelectable = 1 << 0,
+ eValue = 1 << 1,
+ eHyperLink = 1 << 2,
+ eText = 1 << 3
+ };
+ uint8_t mSupportedIfaces;
+
+ private:
+ friend class LocalAccessible;
+ friend class xpcAccessible;
+ friend class xpcAccessibleHyperLink;
+ friend class xpcAccessibleSelectable;
+ friend class xpcAccessibleValue;
+
+ xpcAccessibleGeneric(const xpcAccessibleGeneric&) = delete;
+ xpcAccessibleGeneric& operator=(const xpcAccessibleGeneric&) = delete;
+};
+
+inline LocalAccessible* xpcAccessible::Intl() {
+ if (!static_cast<xpcAccessibleGeneric*>(this)->mIntl) {
+ return nullptr;
+ }
+ return static_cast<xpcAccessibleGeneric*>(this)->mIntl->AsLocal();
+}
+
+inline Accessible* xpcAccessible::IntlGeneric() {
+ return static_cast<xpcAccessibleGeneric*>(this)->mIntl;
+}
+
+inline Accessible* xpcAccessibleHyperLink::Intl() {
+ return static_cast<xpcAccessibleGeneric*>(this)->mIntl;
+}
+
+inline Accessible* xpcAccessibleSelectable::Intl() {
+ return static_cast<xpcAccessibleGeneric*>(this)->mIntl;
+}
+
+inline Accessible* xpcAccessibleValue::Intl() {
+ return static_cast<xpcAccessibleGeneric*>(this)->mIntl;
+}
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleHyperLink.cpp b/accessible/xpcom/xpcAccessibleHyperLink.cpp
new file mode 100644
index 0000000000..aca8734b13
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleHyperLink.cpp
@@ -0,0 +1,154 @@
+/* -*- 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 "xpcAccessibleHyperLink.h"
+
+#include "LocalAccessible-inl.h"
+#include "mozilla/StaticPrefs_accessibility.h"
+#include "nsNetUtil.h"
+#include "xpcAccessibleDocument.h"
+
+using namespace mozilla::a11y;
+
+NS_IMETHODIMP
+xpcAccessibleHyperLink::GetStartIndex(int32_t* aStartIndex) {
+ NS_ENSURE_ARG_POINTER(aStartIndex);
+ *aStartIndex = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (Intl()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ *aStartIndex = static_cast<int32_t>(Intl()->StartOffset());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperLink::GetEndIndex(int32_t* aEndIndex) {
+ NS_ENSURE_ARG_POINTER(aEndIndex);
+ *aEndIndex = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (Intl()->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ *aEndIndex = static_cast<int32_t>(Intl()->EndOffset());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperLink::GetAnchorCount(int32_t* aAnchorCount) {
+ NS_ENSURE_ARG_POINTER(aAnchorCount);
+ *aAnchorCount = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (Intl()->IsLocal()) {
+ *aAnchorCount = Intl()->AsLocal()->AnchorCount();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ bool isCountValid = false;
+ uint32_t anchorCount = Intl()->AsRemote()->AnchorCount(&isCountValid);
+ if (!isCountValid) return NS_ERROR_FAILURE;
+
+ *aAnchorCount = anchorCount;
+#endif
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperLink::GetURI(int32_t aIndex, nsIURI** aURI) {
+ NS_ENSURE_ARG_POINTER(aURI);
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aIndex < 0) return NS_ERROR_INVALID_ARG;
+
+ if (Intl()->IsLocal()) {
+ if (aIndex >= static_cast<int32_t>(Intl()->AsLocal()->AnchorCount())) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ RefPtr<nsIURI>(Intl()->AsLocal()->AnchorURIAt(aIndex)).forget(aURI);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsCString spec;
+ bool isURIValid = false;
+ Intl()->AsRemote()->AnchorURIAt(aIndex, spec, &isURIValid);
+ if (!isURIValid) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIURI> uri;
+ nsresult rv = NS_NewURI(getter_AddRefs(uri), spec);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ uri.forget(aURI);
+#endif
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperLink::GetAnchor(int32_t aIndex, nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aIndex < 0) return NS_ERROR_INVALID_ARG;
+
+ if (Intl()->IsLocal()) {
+ if (aIndex >= static_cast<int32_t>(Intl()->AsLocal()->AnchorCount())) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(Intl()->AsLocal()->AnchorAt(aIndex)));
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ NS_IF_ADDREF(*aAccessible = ToXPC(Intl()->AsRemote()->AnchorAt(aIndex)));
+#endif
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperLink::GetValid(bool* aValid) {
+ NS_ENSURE_ARG_POINTER(aValid);
+ *aValid = false;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (Intl()->IsLocal()) {
+ *aValid = Intl()->AsLocal()->IsLinkValid();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ *aValid = Intl()->AsRemote()->IsLinkValid();
+#endif
+ }
+
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleHyperLink.h b/accessible/xpcom/xpcAccessibleHyperLink.h
new file mode 100644
index 0000000000..85e686eb54
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleHyperLink.h
@@ -0,0 +1,48 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleHyperLink_h_
+#define mozilla_a11y_xpcAccessibleHyperLink_h_
+
+#include "nsIAccessibleHyperLink.h"
+
+#include "mozilla/a11y/Accessible.h"
+
+class nsIAccessible;
+
+namespace mozilla {
+namespace a11y {
+
+class LocalAccessible;
+
+/**
+ * XPCOM nsIAccessibleHyperLink implementation, used by xpcAccessibleGeneric
+ * class.
+ */
+class xpcAccessibleHyperLink : public nsIAccessibleHyperLink {
+ public:
+ NS_IMETHOD GetAnchorCount(int32_t* aAnchorCount) final;
+ NS_IMETHOD GetStartIndex(int32_t* aStartIndex) final;
+ NS_IMETHOD GetEndIndex(int32_t* aEndIndex) final;
+ NS_IMETHOD GetURI(int32_t aIndex, nsIURI** aURI) final;
+ NS_IMETHOD GetAnchor(int32_t aIndex, nsIAccessible** aAccessible) final;
+ NS_IMETHOD GetValid(bool* aValid) final;
+
+ protected:
+ xpcAccessibleHyperLink() {}
+ virtual ~xpcAccessibleHyperLink() {}
+
+ private:
+ xpcAccessibleHyperLink(const xpcAccessibleHyperLink&) = delete;
+ xpcAccessibleHyperLink& operator=(const xpcAccessibleHyperLink&) = delete;
+
+ Accessible* Intl();
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleHyperText.cpp b/accessible/xpcom/xpcAccessibleHyperText.cpp
new file mode 100644
index 0000000000..65ef3cd46c
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleHyperText.cpp
@@ -0,0 +1,703 @@
+/* -*- 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 "xpcAccessibleHyperText.h"
+
+#include "LocalAccessible-inl.h"
+#include "HyperTextAccessible-inl.h"
+#include "mozilla/a11y/PDocAccessible.h"
+#include "mozilla/StaticPrefs_accessibility.h"
+#include "TextRange.h"
+#include "AccAttributes.h"
+#include "nsComponentManagerUtils.h"
+#include "nsPersistentProperties.h"
+#include "xpcAccessibleDocument.h"
+#include "xpcAccessibleTextRange.h"
+
+#include "nsIMutableArray.h"
+
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+NS_INTERFACE_MAP_BEGIN(xpcAccessibleHyperText)
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleText,
+ mSupportedIfaces & eText)
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleEditableText,
+ mSupportedIfaces & eText)
+ NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIAccessibleHyperText,
+ mSupportedIfaces & eText)
+NS_INTERFACE_MAP_END_INHERITING(xpcAccessibleGeneric)
+
+NS_IMPL_ADDREF_INHERITED(xpcAccessibleHyperText, xpcAccessibleGeneric)
+NS_IMPL_RELEASE_INHERITED(xpcAccessibleHyperText, xpcAccessibleGeneric)
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleText
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetCharacterCount(int32_t* aCharacterCount) {
+ NS_ENSURE_ARG_POINTER(aCharacterCount);
+ *aCharacterCount = 0;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (mIntl->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ *aCharacterCount = static_cast<int32_t>(Intl()->CharacterCount());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetText(int32_t aStartOffset, int32_t aEndOffset,
+ nsAString& aText) {
+ aText.Truncate();
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ Intl()->TextSubstring(aStartOffset, aEndOffset, aText);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetTextBeforeOffset(
+ int32_t aOffset, AccessibleTextBoundary aBoundaryType,
+ int32_t* aStartOffset, int32_t* aEndOffset, nsAString& aText) {
+ NS_ENSURE_ARG_POINTER(aStartOffset);
+ NS_ENSURE_ARG_POINTER(aEndOffset);
+ *aStartOffset = *aEndOffset = 0;
+ aText.Truncate();
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ Intl()->TextBeforeOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset,
+ aText);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetTextAtOffset(int32_t aOffset,
+ AccessibleTextBoundary aBoundaryType,
+ int32_t* aStartOffset,
+ int32_t* aEndOffset, nsAString& aText) {
+ NS_ENSURE_ARG_POINTER(aStartOffset);
+ NS_ENSURE_ARG_POINTER(aEndOffset);
+ *aStartOffset = *aEndOffset = 0;
+ aText.Truncate();
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ Intl()->TextAtOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset, aText);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetTextAfterOffset(int32_t aOffset,
+ AccessibleTextBoundary aBoundaryType,
+ int32_t* aStartOffset,
+ int32_t* aEndOffset,
+ nsAString& aText) {
+ NS_ENSURE_ARG_POINTER(aStartOffset);
+ NS_ENSURE_ARG_POINTER(aEndOffset);
+ *aStartOffset = *aEndOffset = 0;
+ aText.Truncate();
+
+ Intl()->TextAfterOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset,
+ aText);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetCharacterAtOffset(int32_t aOffset,
+ char16_t* aCharacter) {
+ NS_ENSURE_ARG_POINTER(aCharacter);
+ *aCharacter = L'\0';
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ *aCharacter = IntlLocal()->CharAt(aOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ *aCharacter = mIntl->AsRemote()->CharAt(aOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetTextAttributes(
+ bool aIncludeDefAttrs, int32_t aOffset, int32_t* aStartOffset,
+ int32_t* aEndOffset, nsIPersistentProperties** aAttributes) {
+ NS_ENSURE_ARG_POINTER(aStartOffset);
+ NS_ENSURE_ARG_POINTER(aEndOffset);
+ NS_ENSURE_ARG_POINTER(aAttributes);
+ *aStartOffset = *aEndOffset = 0;
+ *aAttributes = nullptr;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ RefPtr<AccAttributes> attributes = Intl()->TextAttributes(
+ aIncludeDefAttrs, aOffset, aStartOffset, aEndOffset);
+ RefPtr<nsPersistentProperties> props = new nsPersistentProperties();
+ 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
+xpcAccessibleHyperText::GetDefaultTextAttributes(
+ nsIPersistentProperties** aAttributes) {
+ NS_ENSURE_ARG_POINTER(aAttributes);
+ *aAttributes = nullptr;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+
+ RefPtr<AccAttributes> attributes = Intl()->DefaultTextAttributes();
+ RefPtr<nsPersistentProperties> props = new nsPersistentProperties();
+ 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
+xpcAccessibleHyperText::GetCharacterExtents(int32_t aOffset, int32_t* aX,
+ int32_t* aY, int32_t* aWidth,
+ int32_t* aHeight,
+ uint32_t aCoordType) {
+ NS_ENSURE_ARG_POINTER(aX);
+ NS_ENSURE_ARG_POINTER(aY);
+ NS_ENSURE_ARG_POINTER(aWidth);
+ NS_ENSURE_ARG_POINTER(aHeight);
+ *aX = *aY = *aWidth = *aHeight;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (mIntl->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ LayoutDeviceIntRect rect = Intl()->CharBounds(aOffset, aCoordType);
+ rect.GetRect(aX, aY, aWidth, aHeight);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetRangeExtents(int32_t aStartOffset,
+ int32_t aEndOffset, int32_t* aX,
+ int32_t* aY, int32_t* aWidth,
+ int32_t* aHeight, uint32_t aCoordType) {
+ NS_ENSURE_ARG_POINTER(aX);
+ NS_ENSURE_ARG_POINTER(aY);
+ NS_ENSURE_ARG_POINTER(aWidth);
+ NS_ENSURE_ARG_POINTER(aHeight);
+ *aX = *aY = *aWidth = *aHeight = 0;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (mIntl->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ LayoutDeviceIntRect rect =
+ Intl()->TextBounds(aStartOffset, aEndOffset, aCoordType);
+ rect.GetRect(aX, aY, aWidth, aHeight);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetOffsetAtPoint(int32_t aX, int32_t aY,
+ uint32_t aCoordType,
+ int32_t* aOffset) {
+ NS_ENSURE_ARG_POINTER(aOffset);
+ *aOffset = -1;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ *aOffset = Intl()->OffsetAtPoint(aX, aY, aCoordType);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetCaretOffset(int32_t* aCaretOffset) {
+ NS_ENSURE_ARG_POINTER(aCaretOffset);
+ *aCaretOffset = -1;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ *aCaretOffset = Intl()->CaretOffset();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::SetCaretOffset(int32_t aCaretOffset) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ Intl()->SetCaretOffset(aCaretOffset);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetSelectionCount(int32_t* aSelectionCount) {
+ NS_ENSURE_ARG_POINTER(aSelectionCount);
+ *aSelectionCount = 0;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (mIntl->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ *aSelectionCount = Intl()->SelectionCount();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetSelectionBounds(int32_t aSelectionNum,
+ int32_t* aStartOffset,
+ int32_t* aEndOffset) {
+ NS_ENSURE_ARG_POINTER(aStartOffset);
+ NS_ENSURE_ARG_POINTER(aEndOffset);
+ *aStartOffset = *aEndOffset = 0;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (aSelectionNum < 0) return NS_ERROR_INVALID_ARG;
+
+ if (mIntl->IsLocal() ||
+ StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ if (aSelectionNum >= Intl()->SelectionCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ Intl()->SelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsString unused;
+ mIntl->AsRemote()->SelectionBoundsAt(aSelectionNum, unused, aStartOffset,
+ aEndOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::SetSelectionBounds(int32_t aSelectionNum,
+ int32_t aStartOffset,
+ int32_t aEndOffset) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (aSelectionNum < 0) return NS_ERROR_INVALID_ARG;
+
+ if (mIntl->IsLocal()) {
+ if (!IntlLocal()->SetSelectionBoundsAt(aSelectionNum, aStartOffset,
+ aEndOffset)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ if (!mIntl->AsRemote()->SetSelectionBoundsAt(aSelectionNum, aStartOffset,
+ aEndOffset)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::AddSelection(int32_t aStartOffset, int32_t aEndOffset) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ IntlLocal()->AddToSelection(aStartOffset, aEndOffset);
+ } else {
+ mIntl->AsRemote()->AddToSelection(aStartOffset, aEndOffset);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::RemoveSelection(int32_t aSelectionNum) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ IntlLocal()->RemoveFromSelection(aSelectionNum);
+ } else {
+ mIntl->AsRemote()->RemoveFromSelection(aSelectionNum);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::ScrollSubstringTo(int32_t aStartOffset,
+ int32_t aEndOffset,
+ uint32_t aScrollType) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ IntlLocal()->ScrollSubstringTo(aStartOffset, aEndOffset, aScrollType);
+ } else {
+ mIntl->AsRemote()->ScrollSubstringTo(aStartOffset, aEndOffset, aScrollType);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::ScrollSubstringToPoint(int32_t aStartOffset,
+ int32_t aEndOffset,
+ uint32_t aCoordinateType,
+ int32_t aX, int32_t aY) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ IntlLocal()->ScrollSubstringToPoint(aStartOffset, aEndOffset,
+ aCoordinateType, aX, aY);
+ } else {
+ mIntl->AsRemote()->ScrollSubstringToPoint(aStartOffset, aEndOffset,
+ aCoordinateType, aX, aY);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetEnclosingRange(nsIAccessibleTextRange** aRange) {
+ NS_ENSURE_ARG_POINTER(aRange);
+ *aRange = nullptr;
+
+ if (!IntlLocal()) return NS_ERROR_FAILURE;
+
+ TextRange range;
+ IntlLocal()->EnclosingRange(range);
+ NS_ASSERTION(range.IsValid(), "Should always have an enclosing range!");
+ RefPtr<xpcAccessibleTextRange> xpcRange = new xpcAccessibleTextRange(range);
+
+ xpcRange.forget(aRange);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetSelectionRanges(nsIArray** aRanges) {
+ NS_ENSURE_ARG_POINTER(aRanges);
+ *aRanges = nullptr;
+
+ if (!IntlLocal() && !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMutableArray> xpcRanges =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ AutoTArray<TextRange, 1> ranges;
+ Intl()->SelectionRanges(&ranges);
+ uint32_t len = ranges.Length();
+ for (uint32_t idx = 0; idx < len; idx++) {
+ xpcRanges->AppendElement(new xpcAccessibleTextRange(ranges[idx]));
+ }
+
+ xpcRanges.forget(aRanges);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetVisibleRanges(nsIArray** aRanges) {
+ NS_ENSURE_ARG_POINTER(aRanges);
+ *aRanges = nullptr;
+
+ if (!IntlLocal()) return NS_ERROR_FAILURE;
+
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMutableArray> xpcRanges =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsTArray<TextRange> ranges;
+ IntlLocal()->VisibleRanges(&ranges);
+ uint32_t len = ranges.Length();
+ for (uint32_t idx = 0; idx < len; idx++) {
+ xpcRanges->AppendElement(new xpcAccessibleTextRange(ranges[idx]));
+ }
+
+ xpcRanges.forget(aRanges);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetRangeByChild(nsIAccessible* aChild,
+ nsIAccessibleTextRange** aRange) {
+ NS_ENSURE_ARG_POINTER(aRange);
+ *aRange = nullptr;
+
+ if (!IntlLocal()) return NS_ERROR_FAILURE;
+
+ LocalAccessible* child = aChild->ToInternalAccessible();
+ if (child) {
+ TextRange range;
+ IntlLocal()->RangeByChild(child, range);
+ if (range.IsValid()) {
+ RefPtr<xpcAccessibleTextRange> xpcRange =
+ new xpcAccessibleTextRange(range);
+ xpcRange.forget(aRange);
+ }
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetRangeAtPoint(int32_t aX, int32_t aY,
+ nsIAccessibleTextRange** aRange) {
+ NS_ENSURE_ARG_POINTER(aRange);
+ *aRange = nullptr;
+
+ if (!IntlLocal()) return NS_ERROR_FAILURE;
+
+ TextRange range;
+ IntlLocal()->RangeAtPoint(aX, aY, range);
+ if (range.IsValid()) {
+ RefPtr<xpcAccessibleTextRange> xpcRange = new xpcAccessibleTextRange(range);
+ xpcRange.forget(aRange);
+ }
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleEditableText
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::SetTextContents(const nsAString& aText) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ IntlLocal()->ReplaceText(aText);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsString text(aText);
+ mIntl->AsRemote()->ReplaceText(text);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::InsertText(const nsAString& aText, int32_t aOffset) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ IntlLocal()->InsertText(aText, aOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsString text(aText);
+ mIntl->AsRemote()->InsertText(text, aOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::CopyText(int32_t aStartOffset, int32_t aEndOffset) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ IntlLocal()->CopyText(aStartOffset, aEndOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ mIntl->AsRemote()->CopyText(aStartOffset, aEndOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::CutText(int32_t aStartOffset, int32_t aEndOffset) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ IntlLocal()->CutText(aStartOffset, aEndOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ mIntl->AsRemote()->CutText(aStartOffset, aEndOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::DeleteText(int32_t aStartOffset, int32_t aEndOffset) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ IntlLocal()->DeleteText(aStartOffset, aEndOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ mIntl->AsRemote()->DeleteText(aStartOffset, aEndOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::PasteText(int32_t aOffset) {
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ if (mIntl->IsLocal()) {
+ RefPtr<HyperTextAccessible> acc = IntlLocal();
+ acc->PasteText(aOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ mIntl->AsRemote()->PasteText(aOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleHyperText
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetLinkCount(int32_t* aLinkCount) {
+ NS_ENSURE_ARG_POINTER(aLinkCount);
+ *aLinkCount = 0;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (mIntl->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ *aLinkCount = static_cast<int32_t>(Intl()->LinkCount());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetLinkAt(int32_t aIndex,
+ nsIAccessibleHyperLink** aLink) {
+ NS_ENSURE_ARG_POINTER(aLink);
+ *aLink = nullptr;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (mIntl->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ NS_IF_ADDREF(*aLink = ToXPC(Intl()->LinkAt(aIndex)));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetLinkIndex(nsIAccessibleHyperLink* aLink,
+ int32_t* aIndex) {
+ NS_ENSURE_ARG_POINTER(aLink);
+ NS_ENSURE_ARG_POINTER(aIndex);
+ *aIndex = -1;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIAccessible> xpcLink(do_QueryInterface(aLink));
+ Accessible* accLink = xpcLink->ToInternalGeneric();
+#if defined(XP_WIN)
+ if (accLink->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+ *aIndex = Intl()->LinkIndexOf(accLink);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetLinkIndexAtOffset(int32_t aOffset,
+ int32_t* aLinkIndex) {
+ NS_ENSURE_ARG_POINTER(aLinkIndex);
+ *aLinkIndex = -1; // API says this magic value means 'not found'
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+#if defined(XP_WIN)
+ if (mIntl->IsRemote() &&
+ !StaticPrefs::accessibility_cache_enabled_AtStartup()) {
+ return NS_ERROR_NOT_IMPLEMENTED;
+ }
+#endif
+
+ *aLinkIndex = Intl()->LinkIndexAtOffset(aOffset);
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleHyperText.h b/accessible/xpcom/xpcAccessibleHyperText.h
new file mode 100644
index 0000000000..06cdba2d7a
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleHyperText.h
@@ -0,0 +1,57 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleHyperText_h_
+#define mozilla_a11y_xpcAccessibleHyperText_h_
+
+#include "nsIAccessibleText.h"
+#include "nsIAccessibleHyperText.h"
+#include "nsIAccessibleEditableText.h"
+
+#include "HyperTextAccessible.h"
+#include "xpcAccessibleGeneric.h"
+
+namespace mozilla {
+namespace a11y {
+
+class xpcAccessibleHyperText : public xpcAccessibleGeneric,
+ public nsIAccessibleText,
+ public nsIAccessibleEditableText,
+ public nsIAccessibleHyperText {
+ public:
+ explicit xpcAccessibleHyperText(Accessible* aIntl)
+ : xpcAccessibleGeneric(aIntl) {
+ if (aIntl->IsHyperText() && aIntl->IsTextRole()) mSupportedIfaces |= eText;
+ }
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_DECL_NSIACCESSIBLETEXT
+ NS_DECL_NSIACCESSIBLEHYPERTEXT
+ NS_DECL_NSIACCESSIBLEEDITABLETEXT
+
+ protected:
+ virtual ~xpcAccessibleHyperText() {}
+
+ private:
+ HyperTextAccessibleBase* Intl() { return mIntl->AsHyperTextBase(); }
+
+ HyperTextAccessible* IntlLocal() {
+ if (LocalAccessible* acc = mIntl->AsLocal()) {
+ return acc->AsHyperText();
+ }
+
+ return nullptr;
+ }
+
+ xpcAccessibleHyperText(const xpcAccessibleHyperText&) = delete;
+ xpcAccessibleHyperText& operator=(const xpcAccessibleHyperText&) = delete;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // mozilla_a11y_xpcAccessibleHyperText_h_
diff --git a/accessible/xpcom/xpcAccessibleImage.cpp b/accessible/xpcom/xpcAccessibleImage.cpp
new file mode 100644
index 0000000000..ec899346aa
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleImage.cpp
@@ -0,0 +1,51 @@
+/* -*- 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 "xpcAccessibleImage.h"
+
+#include "ImageAccessible.h"
+
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+NS_IMPL_ISUPPORTS_INHERITED(xpcAccessibleImage, xpcAccessibleGeneric,
+ nsIAccessibleImage)
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleImage
+
+NS_IMETHODIMP
+xpcAccessibleImage::GetImagePosition(uint32_t aCoordType, int32_t* aX,
+ int32_t* aY) {
+ NS_ENSURE_ARG_POINTER(aX);
+ *aX = 0;
+ NS_ENSURE_ARG_POINTER(aY);
+ *aY = 0;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ LayoutDeviceIntPoint point = mIntl->Position(aCoordType);
+ *aX = point.x;
+ *aY = point.y;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleImage::GetImageSize(int32_t* aWidth, int32_t* aHeight) {
+ NS_ENSURE_ARG_POINTER(aWidth);
+ *aWidth = 0;
+ NS_ENSURE_ARG_POINTER(aHeight);
+ *aHeight = 0;
+
+ if (!mIntl) return NS_ERROR_FAILURE;
+
+ LayoutDeviceIntSize size = mIntl->Size();
+ *aWidth = size.width;
+ *aHeight = size.height;
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleImage.h b/accessible/xpcom/xpcAccessibleImage.h
new file mode 100644
index 0000000000..ca70ab35f8
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleImage.h
@@ -0,0 +1,40 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleImage_h_
+#define mozilla_a11y_xpcAccessibleImage_h_
+
+#include "nsIAccessibleImage.h"
+
+#include "xpcAccessibleGeneric.h"
+
+namespace mozilla {
+namespace a11y {
+
+class xpcAccessibleImage : public xpcAccessibleGeneric,
+ public nsIAccessibleImage {
+ public:
+ explicit xpcAccessibleImage(Accessible* aIntl)
+ : xpcAccessibleGeneric(aIntl) {}
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_IMETHOD GetImagePosition(uint32_t aCoordType, int32_t* aX,
+ int32_t* aY) final;
+ NS_IMETHOD GetImageSize(int32_t* aWidth, int32_t* aHeight) final;
+
+ protected:
+ virtual ~xpcAccessibleImage() {}
+
+ private:
+ xpcAccessibleImage(const xpcAccessibleImage&) = delete;
+ xpcAccessibleImage& operator=(const xpcAccessibleImage&) = delete;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleMacInterface.h b/accessible/xpcom/xpcAccessibleMacInterface.h
new file mode 100644
index 0000000000..18b5955087
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleMacInterface.h
@@ -0,0 +1,104 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleMacInterface_h_
+#define mozilla_a11y_xpcAccessibleMacInterface_h_
+
+#include "mozilla/a11y/Accessible.h"
+#include "nsIAccessibleMacInterface.h"
+
+class nsIAccessibleMacInterface;
+
+namespace mozilla {
+namespace a11y {
+
+class xpcAccessibleMacNSObjectWrapper : public nsIAccessibleMacNSObjectWrapper {
+ public:
+ explicit xpcAccessibleMacNSObjectWrapper(id aTextMarker);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIACCESSIBLEMACNSOBJECTWRAPPER
+
+ protected:
+ virtual ~xpcAccessibleMacNSObjectWrapper();
+
+ id mNativeObject;
+};
+
+class xpcAccessibleMacInterface : public xpcAccessibleMacNSObjectWrapper,
+ public nsIAccessibleMacInterface {
+ public:
+ // Construct an xpcAccessibleMacInterface using this
+ // native object that conforms to the NSAccessibility protocol.
+ explicit xpcAccessibleMacInterface(id aNativeObj)
+ : xpcAccessibleMacNSObjectWrapper(aNativeObj) {}
+
+ // Construct an xpcAccessibleMacInterface using the native object
+ // associated with this accessible.
+ explicit xpcAccessibleMacInterface(Accessible* aObj);
+
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_NSIACCESSIBLEMACINTERFACE
+
+ // Convert an NSObject (which can be anything, string, number, array, etc.)
+ // into a properly typed js value populated in the aResult handle.
+ static nsresult NSObjectToJsValue(id aObj, JSContext* aCx,
+ JS::MutableHandleValue aResult);
+
+ protected:
+ virtual ~xpcAccessibleMacInterface() {}
+
+ // Return true if our native object responds to this selector and
+ // if it implements isAccessibilitySelectorAllowed check that it returns true
+ // too.
+ bool SupportsSelector(SEL aSelector);
+
+ // Convert a js value to an NSObject. This is called recursively for arrays.
+ // If the conversion fails, aResult is set to an error and nil is returned.
+ id JsValueToNSObject(JS::HandleValue aValue, JSContext* aCx,
+ nsresult* aResult);
+
+ // Convert a js value to an NSValue NSObject. This is called
+ // by JsValueToNSObject when encountering a JS object with
+ // a "value" and "valueType" property.
+ id JsValueToNSValue(JS::HandleObject aObject, JSContext* aCx,
+ nsresult* aResult);
+
+ // Convert a js value to a specified NSObject. This is called
+ // by JsValueToNSObject when encountering a JS object with
+ // a "object" and "objcetType" property.
+ id JsValueToSpecifiedNSObject(JS::HandleObject aObject, JSContext* aCx,
+ nsresult* aResult);
+
+ private:
+ xpcAccessibleMacInterface(const xpcAccessibleMacInterface&) = delete;
+ xpcAccessibleMacInterface& operator=(const xpcAccessibleMacInterface&) =
+ delete;
+};
+
+class xpcAccessibleMacEvent : public nsIAccessibleMacEvent {
+ public:
+ explicit xpcAccessibleMacEvent(id aNativeObj, id aData);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIACCESSIBLEMACEVENT;
+
+ // This sends notifications via nsIObserverService to be consumed by our
+ // mochitests. aNativeObj is a NSAccessibility protocol object,
+ // and aNotification is a NSString.
+ static void FireEvent(id aNativeObj, id aNotification, id aUserInfo);
+
+ protected:
+ virtual ~xpcAccessibleMacEvent();
+
+ id mNativeObject;
+ id mData;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleMacInterface.mm b/accessible/xpcom/xpcAccessibleMacInterface.mm
new file mode 100644
index 0000000000..a266791579
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleMacInterface.mm
@@ -0,0 +1,539 @@
+/* clang-format off */
+/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* clang-format on */
+/* 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 "xpcAccessibleMacInterface.h"
+
+#include "nsCocoaUtils.h"
+#include "nsContentUtils.h"
+#include "nsIObserverService.h"
+#include "nsISimpleEnumerator.h"
+#include "nsIXPConnect.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "mozilla/Services.h"
+#include "nsString.h"
+#include "js/PropertyAndElement.h" // JS_Enumerate, JS_GetElement, JS_GetProperty, JS_GetPropertyById, JS_HasOwnProperty, JS_SetUCProperty
+
+#import "mozAccessible.h"
+
+using namespace mozilla::a11y;
+
+// xpcAccessibleMacNSObjectWrapper
+
+NS_IMPL_ISUPPORTS(xpcAccessibleMacNSObjectWrapper, nsIAccessibleMacNSObjectWrapper)
+
+xpcAccessibleMacNSObjectWrapper::xpcAccessibleMacNSObjectWrapper(id aNativeObj)
+ : mNativeObject(aNativeObj) {
+ [mNativeObject retain];
+}
+
+xpcAccessibleMacNSObjectWrapper::~xpcAccessibleMacNSObjectWrapper() { [mNativeObject release]; }
+
+id xpcAccessibleMacNSObjectWrapper::GetNativeObject() { return mNativeObject; }
+
+// xpcAccessibleMacInterface
+
+NS_IMPL_ISUPPORTS_INHERITED(xpcAccessibleMacInterface, xpcAccessibleMacNSObjectWrapper,
+ nsIAccessibleMacInterface)
+
+xpcAccessibleMacInterface::xpcAccessibleMacInterface(Accessible* aObj)
+ : xpcAccessibleMacNSObjectWrapper(GetNativeFromGeckoAccessible(aObj)) {}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::GetAttributeNames(nsTArray<nsString>& aAttributeNames) {
+ NS_OBJC_BEGIN_TRY_BLOCK_RETURN
+
+ if (!mNativeObject || [mNativeObject isExpired]) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ for (NSString* name in [mNativeObject accessibilityAttributeNames]) {
+ nsAutoString attribName;
+ nsCocoaUtils::GetStringForNSString(name, attribName);
+ aAttributeNames.AppendElement(attribName);
+ }
+
+ return NS_OK;
+
+ NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::GetParameterizedAttributeNames(nsTArray<nsString>& aAttributeNames) {
+ NS_OBJC_BEGIN_TRY_BLOCK_RETURN
+
+ if (!mNativeObject || [mNativeObject isExpired]) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ for (NSString* name in [mNativeObject accessibilityParameterizedAttributeNames]) {
+ nsAutoString attribName;
+ nsCocoaUtils::GetStringForNSString(name, attribName);
+ aAttributeNames.AppendElement(attribName);
+ }
+
+ return NS_OK;
+
+ NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::GetActionNames(nsTArray<nsString>& aActionNames) {
+ NS_OBJC_BEGIN_TRY_BLOCK_RETURN
+
+ if (!mNativeObject || [mNativeObject isExpired]) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ for (NSString* name in [mNativeObject accessibilityActionNames]) {
+ nsAutoString actionName;
+ nsCocoaUtils::GetStringForNSString(name, actionName);
+ aActionNames.AppendElement(actionName);
+ }
+
+ return NS_OK;
+
+ NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::PerformAction(const nsAString& aActionName) {
+ NS_OBJC_BEGIN_TRY_BLOCK_RETURN
+
+ if (!mNativeObject || [mNativeObject isExpired]) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ NSString* actionName = nsCocoaUtils::ToNSString(aActionName);
+ [mNativeObject accessibilityPerformAction:actionName];
+
+ return NS_OK;
+
+ NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::GetAttributeValue(const nsAString& aAttributeName, JSContext* aCx,
+ JS::MutableHandleValue aResult) {
+ NS_OBJC_BEGIN_TRY_BLOCK_RETURN
+
+ if (!mNativeObject || [mNativeObject isExpired]) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ NSString* attribName = nsCocoaUtils::ToNSString(aAttributeName);
+ return NSObjectToJsValue([mNativeObject accessibilityAttributeValue:attribName], aCx, aResult);
+
+ NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE)
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::IsAttributeSettable(const nsAString& aAttributeName, bool* aIsSettable) {
+ NS_ENSURE_ARG_POINTER(aIsSettable);
+
+ NSString* attribName = nsCocoaUtils::ToNSString(aAttributeName);
+ if ([mNativeObject respondsToSelector:@selector(accessibilityIsAttributeSettable:)]) {
+ *aIsSettable = [mNativeObject accessibilityIsAttributeSettable:attribName];
+ return NS_OK;
+ }
+
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::SetAttributeValue(const nsAString& aAttributeName,
+ JS::HandleValue aAttributeValue, JSContext* aCx) {
+ nsresult rv = NS_OK;
+ id obj = JsValueToNSObject(aAttributeValue, aCx, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NSString* attribName = nsCocoaUtils::ToNSString(aAttributeName);
+ if ([mNativeObject respondsToSelector:@selector(accessibilitySetValue:forAttribute:)]) {
+ // The NSObject has an attribute setter, call that.
+ [mNativeObject accessibilitySetValue:obj forAttribute:attribName];
+ return NS_OK;
+ }
+
+ return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::GetParameterizedAttributeValue(const nsAString& aAttributeName,
+ JS::HandleValue aParameter,
+ JSContext* aCx,
+ JS::MutableHandleValue aResult) {
+ nsresult rv = NS_OK;
+ id paramObj = JsValueToNSObject(aParameter, aCx, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ NSString* attribName = nsCocoaUtils::ToNSString(aAttributeName);
+ return NSObjectToJsValue(
+ [mNativeObject accessibilityAttributeValue:attribName forParameter:paramObj], aCx, aResult);
+}
+
+bool xpcAccessibleMacInterface::SupportsSelector(SEL aSelector) {
+ // return true if we have this selector, and if isAccessibilitySelectorAllowed
+ // is implemented too whether it is "allowed".
+ return [mNativeObject respondsToSelector:aSelector] &&
+ (![mNativeObject respondsToSelector:@selector(isAccessibilitySelectorAllowed:selector:)] ||
+ [mNativeObject isAccessibilitySelectorAllowed:aSelector]);
+}
+
+nsresult xpcAccessibleMacInterface::NSObjectToJsValue(id aObj, JSContext* aCx,
+ JS::MutableHandleValue aResult) {
+ if (!aObj) {
+ aResult.set(JS::NullValue());
+ } else if ([aObj isKindOfClass:[NSString class]]) {
+ nsAutoString strVal;
+ nsCocoaUtils::GetStringForNSString((NSString*)aObj, strVal);
+ if (!mozilla::dom::ToJSValue(aCx, strVal, aResult)) {
+ return NS_ERROR_FAILURE;
+ }
+ } else if ([aObj isKindOfClass:[NSNumber class]]) {
+ // If the type being held by the NSNumber is a BOOL set js value
+ // to boolean. Otherwise use a double value.
+ if (strcmp([(NSNumber*)aObj objCType], @encode(BOOL)) == 0) {
+ if (!mozilla::dom::ToJSValue(aCx, [(NSNumber*)aObj boolValue], aResult)) {
+ return NS_ERROR_FAILURE;
+ }
+ } else {
+ if (!mozilla::dom::ToJSValue(aCx, [(NSNumber*)aObj doubleValue], aResult)) {
+ return NS_ERROR_FAILURE;
+ }
+ }
+ } else if ([aObj isKindOfClass:[NSValue class]] &&
+ strcmp([(NSValue*)aObj objCType], @encode(NSPoint)) == 0) {
+ NSPoint point = [(NSValue*)aObj pointValue];
+ return NSObjectToJsValue(
+ @[ [NSNumber numberWithDouble:point.x], [NSNumber numberWithDouble:point.y] ], aCx,
+ aResult);
+ } else if ([aObj isKindOfClass:[NSValue class]] &&
+ strcmp([(NSValue*)aObj objCType], @encode(NSSize)) == 0) {
+ NSSize size = [(NSValue*)aObj sizeValue];
+ return NSObjectToJsValue(
+ @[ [NSNumber numberWithDouble:size.width], [NSNumber numberWithDouble:size.height] ], aCx,
+ aResult);
+ } else if ([aObj isKindOfClass:[NSValue class]] &&
+ strcmp([(NSValue*)aObj objCType], @encode(NSRange)) == 0) {
+ NSRange range = [(NSValue*)aObj rangeValue];
+ return NSObjectToJsValue(@[ @(range.location), @(range.length) ], aCx, aResult);
+ } else if ([aObj isKindOfClass:[NSValue class]] &&
+ strcmp([(NSValue*)aObj objCType], @encode(NSRect)) == 0) {
+ NSRect rect = [(NSValue*)aObj rectValue];
+ return NSObjectToJsValue(@{
+ @"origin" : [NSValue valueWithPoint:rect.origin],
+ @"size" : [NSValue valueWithSize:rect.size]
+ },
+ aCx, aResult);
+ } else if ([aObj isKindOfClass:[NSArray class]]) {
+ NSArray* objArr = (NSArray*)aObj;
+
+ JS::RootedVector<JS::Value> v(aCx);
+ if (!v.resize([objArr count])) {
+ return NS_ERROR_FAILURE;
+ }
+ for (size_t i = 0; i < [objArr count]; ++i) {
+ nsresult rv = NSObjectToJsValue(objArr[i], aCx, v[i]);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ JSObject* arrayObj = JS::NewArrayObject(aCx, v);
+ if (!arrayObj) {
+ return NS_ERROR_FAILURE;
+ }
+ aResult.setObject(*arrayObj);
+ } else if ([aObj isKindOfClass:[NSDictionary class]]) {
+ JS::RootedObject obj(aCx, JS_NewPlainObject(aCx));
+ for (NSString* key in aObj) {
+ nsAutoString strKey;
+ nsCocoaUtils::GetStringForNSString(key, strKey);
+ JS::RootedValue value(aCx);
+ nsresult rv = NSObjectToJsValue(aObj[key], aCx, &value);
+ NS_ENSURE_SUCCESS(rv, rv);
+ JS_SetUCProperty(aCx, obj, strKey.get(), strKey.Length(), value);
+ }
+ aResult.setObject(*obj);
+ } else if ([aObj isKindOfClass:[NSAttributedString class]]) {
+ NSAttributedString* attrStr = (NSAttributedString*)aObj;
+ __block NSMutableArray* attrRunArray = [[NSMutableArray alloc] init];
+
+ [attrStr
+ enumerateAttributesInRange:NSMakeRange(0, [attrStr length])
+ options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
+ usingBlock:^(NSDictionary* attributes, NSRange range, BOOL* stop) {
+ NSString* str = [[attrStr string] substringWithRange:range];
+ if (!str || !attributes) {
+ return;
+ }
+
+ NSMutableDictionary* attrRun = [attributes mutableCopy];
+ attrRun[@"string"] = str;
+
+ [attrRunArray addObject:attrRun];
+ }];
+
+ // The attributed string is represented in js as an array of objects.
+ // Each object represents a run of text where the "string" property is the
+ // string value and all the AX* properties are the attributes.
+ return NSObjectToJsValue(attrRunArray, aCx, aResult);
+ } else if (CFGetTypeID(aObj) == CGColorGetTypeID()) {
+ const CGFloat* components = CGColorGetComponents((CGColorRef)aObj);
+ NSString* hexString =
+ [NSString stringWithFormat:@"#%02x%02x%02x", (int)(components[0] * 0xff),
+ (int)(components[1] * 0xff), (int)(components[2] * 0xff)];
+ return NSObjectToJsValue(hexString, aCx, aResult);
+ } else if ([aObj respondsToSelector:@selector(isAccessibilityElement)]) {
+ // We expect all of our accessibility objects to implement isAccessibilityElement
+ // at the very least. If it is implemented we will assume its an accessibility object.
+ nsCOMPtr<nsIAccessibleMacInterface> obj = new xpcAccessibleMacInterface(aObj);
+ return nsContentUtils::WrapNative(aCx, obj, &NS_GET_IID(nsIAccessibleMacInterface), aResult);
+ } else {
+ // If this is any other kind of NSObject, just wrap it and return it.
+ // It will be opaque and immutable on the JS side, but it can be
+ // brought back to us in an argument.
+ nsCOMPtr<nsIAccessibleMacNSObjectWrapper> obj = new xpcAccessibleMacNSObjectWrapper(aObj);
+ return nsContentUtils::WrapNative(aCx, obj, &NS_GET_IID(nsIAccessibleMacNSObjectWrapper),
+ aResult);
+ }
+
+ return NS_OK;
+}
+
+id xpcAccessibleMacInterface::JsValueToNSObject(JS::HandleValue aValue, JSContext* aCx,
+ nsresult* aResult) {
+ *aResult = NS_OK;
+ if (aValue.isInt32()) {
+ return [NSNumber numberWithInteger:aValue.toInt32()];
+ } else if (aValue.isBoolean()) {
+ return [NSNumber numberWithBool:aValue.toBoolean()];
+ } else if (aValue.isString()) {
+ nsAutoJSString temp;
+ if (!temp.init(aCx, aValue)) {
+ NS_WARNING("cannot init string with given value");
+ *aResult = NS_ERROR_FAILURE;
+ return nil;
+ }
+ return nsCocoaUtils::ToNSString(temp);
+ } else if (aValue.isObject()) {
+ JS::Rooted<JSObject*> obj(aCx, aValue.toObjectOrNull());
+
+ bool isArray;
+ JS::IsArrayObject(aCx, obj, &isArray);
+ if (isArray) {
+ // If this is an array, we construct an NSArray and insert the js
+ // array's elements by recursively calling this function.
+ uint32_t len;
+ JS::GetArrayLength(aCx, obj, &len);
+ NSMutableArray* array = [NSMutableArray arrayWithCapacity:len];
+ for (uint32_t i = 0; i < len; i++) {
+ JS::RootedValue v(aCx);
+ JS_GetElement(aCx, obj, i, &v);
+ [array addObject:JsValueToNSObject(v, aCx, aResult)];
+ NS_ENSURE_SUCCESS(*aResult, nil);
+ }
+ return array;
+ }
+
+ bool hasValueType;
+ bool hasValue;
+ JS_HasOwnProperty(aCx, obj, "valueType", &hasValueType);
+ JS_HasOwnProperty(aCx, obj, "value", &hasValue);
+ if (hasValueType && hasValue) {
+ // A js object representin an NSValue looks like this:
+ // { valueType: "NSRange", value: [1, 3] }
+ return JsValueToNSValue(obj, aCx, aResult);
+ }
+
+ bool hasObjectType;
+ bool hasObject;
+ JS_HasOwnProperty(aCx, obj, "objectType", &hasObjectType);
+ JS_HasOwnProperty(aCx, obj, "object", &hasObject);
+ if (hasObjectType && hasObject) {
+ // A js object representing an NSDictionary looks like this:
+ // { objectType: "NSDictionary", value: {k: v, k: v, ...} }
+ return JsValueToSpecifiedNSObject(obj, aCx, aResult);
+ }
+
+ // This may be another nsIAccessibleMacInterface instance.
+ // If so, return the wrapped NSObject.
+ nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+
+ nsCOMPtr<nsIXPConnectWrappedNative> wrappedObj;
+ nsresult rv = xpc->GetWrappedNativeOfJSObject(aCx, obj, getter_AddRefs(wrappedObj));
+ NS_ENSURE_SUCCESS(rv, nil);
+ nsCOMPtr<nsIAccessibleMacNSObjectWrapper> macObjIface = do_QueryInterface(wrappedObj->Native());
+ return macObjIface->GetNativeObject();
+ }
+
+ *aResult = NS_ERROR_FAILURE;
+ return nil;
+}
+
+id xpcAccessibleMacInterface::JsValueToNSValue(JS::HandleObject aObject, JSContext* aCx,
+ nsresult* aResult) {
+ *aResult = NS_ERROR_FAILURE;
+ JS::RootedValue valueTypeValue(aCx);
+ if (!JS_GetProperty(aCx, aObject, "valueType", &valueTypeValue)) {
+ NS_WARNING("Could not get valueType");
+ return nil;
+ }
+
+ JS::RootedValue valueValue(aCx);
+ if (!JS_GetProperty(aCx, aObject, "value", &valueValue)) {
+ NS_WARNING("Could not get value");
+ return nil;
+ }
+
+ nsAutoJSString valueType;
+ if (!valueTypeValue.isString() || !valueType.init(aCx, valueTypeValue)) {
+ NS_WARNING("valueType is not a string");
+ return nil;
+ }
+
+ bool isArray;
+ JS::IsArrayObject(aCx, valueValue, &isArray);
+ if (!isArray) {
+ NS_WARNING("value is not an array");
+ return nil;
+ }
+
+ JS::Rooted<JSObject*> value(aCx, valueValue.toObjectOrNull());
+
+ if (valueType.EqualsLiteral("NSRange")) {
+ uint32_t len;
+ JS::GetArrayLength(aCx, value, &len);
+ if (len != 2) {
+ NS_WARNING("Expected a 2 member array");
+ return nil;
+ }
+
+ JS::RootedValue locationValue(aCx);
+ JS_GetElement(aCx, value, 0, &locationValue);
+ JS::RootedValue lengthValue(aCx);
+ JS_GetElement(aCx, value, 1, &lengthValue);
+ if (!locationValue.isInt32() || !lengthValue.isInt32()) {
+ NS_WARNING("Expected an array of integers");
+ return nil;
+ }
+
+ *aResult = NS_OK;
+ return [NSValue valueWithRange:NSMakeRange(locationValue.toInt32(), lengthValue.toInt32())];
+ }
+
+ return nil;
+}
+
+id xpcAccessibleMacInterface::JsValueToSpecifiedNSObject(JS::HandleObject aObject, JSContext* aCx,
+ nsresult* aResult) {
+ *aResult = NS_ERROR_FAILURE;
+ JS::RootedValue objectTypeValue(aCx);
+ if (!JS_GetProperty(aCx, aObject, "objectType", &objectTypeValue)) {
+ NS_WARNING("Could not get objectType");
+ return nil;
+ }
+
+ JS::RootedValue objectValue(aCx);
+ if (!JS_GetProperty(aCx, aObject, "object", &objectValue)) {
+ NS_WARNING("Could not get object");
+ return nil;
+ }
+
+ nsAutoJSString objectType;
+ if (!objectTypeValue.isString()) {
+ NS_WARNING("objectType is not a string");
+ return nil;
+ }
+
+ if (!objectType.init(aCx, objectTypeValue)) {
+ NS_WARNING("cannot init string with object type");
+ return nil;
+ }
+
+ bool isObject = objectValue.isObjectOrNull();
+ if (!isObject) {
+ NS_WARNING("object is not a JSON object");
+ return nil;
+ }
+
+ JS::Rooted<JSObject*> object(aCx, objectValue.toObjectOrNull());
+
+ if (objectType.EqualsLiteral("NSDictionary")) {
+ JS::Rooted<JS::IdVector> ids(aCx, JS::IdVector(aCx));
+ if (!JS_Enumerate(aCx, object, &ids)) {
+ NS_WARNING("Unable to get keys from dictionary object");
+ return nil;
+ }
+
+ NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
+
+ for (size_t i = 0, n = ids.length(); i < n; i++) {
+ nsresult rv = NS_OK;
+ // get current key
+ JS::RootedValue currentKey(aCx);
+ JS_IdToValue(aCx, ids[i], &currentKey);
+ id unwrappedKey = JsValueToNSObject(currentKey, aCx, &rv);
+ NS_ENSURE_SUCCESS(rv, nil);
+ MOZ_ASSERT([unwrappedKey isKindOfClass:[NSString class]]);
+
+ // get associated value for current key
+ JS::RootedValue currentValue(aCx);
+ JS_GetPropertyById(aCx, object, ids[i], &currentValue);
+ id unwrappedValue = JsValueToNSObject(currentValue, aCx, &rv);
+ NS_ENSURE_SUCCESS(rv, nil);
+ dict[unwrappedKey] = unwrappedValue;
+ }
+
+ *aResult = NS_OK;
+ return dict;
+ }
+
+ return nil;
+}
+
+NS_IMPL_ISUPPORTS(xpcAccessibleMacEvent, nsIAccessibleMacEvent)
+
+xpcAccessibleMacEvent::xpcAccessibleMacEvent(id aNativeObj, id aData)
+ : mNativeObject(aNativeObj), mData(aData) {
+ [mNativeObject retain];
+ [mData retain];
+}
+
+xpcAccessibleMacEvent::~xpcAccessibleMacEvent() {
+ [mNativeObject release];
+ [mData release];
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacEvent::GetMacIface(nsIAccessibleMacInterface** aMacIface) {
+ RefPtr<xpcAccessibleMacInterface> macIface = new xpcAccessibleMacInterface(mNativeObject);
+ macIface.forget(aMacIface);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacEvent::GetData(JSContext* aCx, JS::MutableHandleValue aData) {
+ return xpcAccessibleMacInterface::NSObjectToJsValue(mData, aCx, aData);
+}
+
+void xpcAccessibleMacEvent::FireEvent(id aNativeObj, id aNotification, id aUserInfo) {
+ if (nsCOMPtr<nsIObserverService> obsService = services::GetObserverService()) {
+ nsCOMPtr<nsISimpleEnumerator> observers;
+ // Get all observers for the mac event topic.
+ obsService->EnumerateObservers(NS_ACCESSIBLE_MAC_EVENT_TOPIC, getter_AddRefs(observers));
+ if (observers) {
+ bool hasObservers = false;
+ observers->HasMoreElements(&hasObservers);
+ // If we have observers, notify them.
+ if (hasObservers) {
+ nsCOMPtr<nsIAccessibleMacEvent> xpcIface = new xpcAccessibleMacEvent(aNativeObj, aUserInfo);
+ nsAutoString notificationStr;
+ nsCocoaUtils::GetStringForNSString(aNotification, notificationStr);
+ obsService->NotifyObservers(xpcIface, NS_ACCESSIBLE_MAC_EVENT_TOPIC, notificationStr.get());
+ }
+ }
+ }
+}
diff --git a/accessible/xpcom/xpcAccessibleSelectable.cpp b/accessible/xpcom/xpcAccessibleSelectable.cpp
new file mode 100644
index 0000000000..1eb0cb987a
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleSelectable.cpp
@@ -0,0 +1,121 @@
+/* -*- 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 "Accessible.h"
+
+#include "nsComponentManagerUtils.h"
+#include "nsIAccessible.h"
+#include "nsIMutableArray.h"
+#include "xpcAccessibleDocument.h"
+#include "xpcAccessibleSelectable.h"
+
+using namespace mozilla::a11y;
+
+NS_IMETHODIMP
+xpcAccessibleSelectable::GetSelectedItems(nsIArray** aSelectedItems) {
+ NS_ENSURE_ARG_POINTER(aSelectedItems);
+ *aSelectedItems = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+ MOZ_ASSERT(Intl()->IsSelect(), "Called on non selectable widget!");
+
+ AutoTArray<Accessible*, 10> items;
+ Intl()->SelectedItems(&items);
+
+ uint32_t itemCount = items.Length();
+ if (itemCount == 0) return NS_OK;
+
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMutableArray> xpcItems =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ for (uint32_t idx = 0; idx < itemCount; idx++) {
+ xpcItems->AppendElement(static_cast<nsIAccessible*>(ToXPC(items[idx])));
+ }
+
+ NS_ADDREF(*aSelectedItems = xpcItems);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleSelectable::GetSelectedItemCount(uint32_t* aSelectionCount) {
+ NS_ENSURE_ARG_POINTER(aSelectionCount);
+ *aSelectionCount = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+ MOZ_ASSERT(Intl()->IsSelect(), "Called on non selectable widget!");
+
+ *aSelectionCount = Intl()->SelectedItemCount();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleSelectable::GetSelectedItemAt(uint32_t aIndex,
+ nsIAccessible** aSelected) {
+ NS_ENSURE_ARG_POINTER(aSelected);
+ *aSelected = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+ MOZ_ASSERT(Intl()->IsSelect(), "Called on non selectable widget!");
+
+ *aSelected = ToXPC(Intl()->GetSelectedItem(aIndex));
+ if (*aSelected) {
+ NS_ADDREF(*aSelected);
+ return NS_OK;
+ }
+
+ return NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+xpcAccessibleSelectable::IsItemSelected(uint32_t aIndex, bool* aIsSelected) {
+ NS_ENSURE_ARG_POINTER(aIsSelected);
+ *aIsSelected = false;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+ MOZ_ASSERT(Intl()->IsSelect(), "Called on non selectable widget!");
+
+ *aIsSelected = Intl()->IsItemSelected(aIndex);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleSelectable::AddItemToSelection(uint32_t aIndex) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+ MOZ_ASSERT(Intl()->IsSelect(), "Called on non selectable widget!");
+
+ return Intl()->AddItemToSelection(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+xpcAccessibleSelectable::RemoveItemFromSelection(uint32_t aIndex) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+ MOZ_ASSERT(Intl()->IsSelect(), "Called on non selectable widget!");
+
+ return Intl()->RemoveItemFromSelection(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG;
+}
+
+NS_IMETHODIMP
+xpcAccessibleSelectable::SelectAll(bool* aIsMultiSelect) {
+ NS_ENSURE_ARG_POINTER(aIsMultiSelect);
+ *aIsMultiSelect = false;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+ MOZ_ASSERT(Intl()->IsSelect(), "Called on non selectable widget!");
+
+ *aIsMultiSelect = Intl()->SelectAll();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleSelectable::UnselectAll() {
+ if (!Intl()) return NS_ERROR_FAILURE;
+ MOZ_ASSERT(Intl()->IsSelect(), "Called on non selectable widget!");
+
+ Intl()->UnselectAll();
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleSelectable.h b/accessible/xpcom/xpcAccessibleSelectable.h
new file mode 100644
index 0000000000..706690df2e
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleSelectable.h
@@ -0,0 +1,50 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleSelectable_h_
+#define mozilla_a11y_xpcAccessibleSelectable_h_
+
+#include "nsIAccessibleSelectable.h"
+
+class nsIAccessible;
+class nsIArray;
+
+namespace mozilla {
+namespace a11y {
+
+class Accessible;
+
+/**
+ * XPCOM nsIAccessibleSelectable inteface implementation, used by
+ * xpcAccessibleGeneric class.
+ */
+class xpcAccessibleSelectable : public nsIAccessibleSelectable {
+ public:
+ // nsIAccessibleSelectable
+ NS_IMETHOD GetSelectedItems(nsIArray** aSelectedItems) final;
+ NS_IMETHOD GetSelectedItemCount(uint32_t* aSelectedItemCount) final;
+ NS_IMETHOD GetSelectedItemAt(uint32_t aIndex, nsIAccessible** aItem) final;
+ NS_IMETHOD IsItemSelected(uint32_t aIndex, bool* aIsSelected) final;
+ NS_IMETHOD AddItemToSelection(uint32_t aIndex) final;
+ NS_IMETHOD RemoveItemFromSelection(uint32_t aIndex) final;
+ NS_IMETHOD SelectAll(bool* aIsMultiSelect) final;
+ NS_IMETHOD UnselectAll() final;
+
+ protected:
+ xpcAccessibleSelectable() {}
+ virtual ~xpcAccessibleSelectable() {}
+
+ private:
+ xpcAccessibleSelectable(const xpcAccessibleSelectable&) = delete;
+ xpcAccessibleSelectable& operator=(const xpcAccessibleSelectable&) = delete;
+
+ Accessible* Intl();
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleTable.cpp b/accessible/xpcom/xpcAccessibleTable.cpp
new file mode 100644
index 0000000000..0bb541bfaa
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTable.cpp
@@ -0,0 +1,411 @@
+/* -*- 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 "xpcAccessibleTable.h"
+
+#include "mozilla/a11y/Accessible.h"
+#include "mozilla/a11y/TableAccessibleBase.h"
+
+#include "nsIMutableArray.h"
+#include "nsComponentManagerUtils.h"
+#include "xpcAccessibleDocument.h"
+
+using namespace mozilla::a11y;
+
+static const uint32_t XPC_TABLE_DEFAULT_SIZE = 40;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+NS_IMPL_ISUPPORTS_INHERITED(xpcAccessibleTable, xpcAccessibleHyperText,
+ nsIAccessibleTable)
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleTable
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetCaption(nsIAccessible** aCaption) {
+ NS_ENSURE_ARG_POINTER(aCaption);
+ *aCaption = nullptr;
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aCaption = ToXPC(Intl()->Caption()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetColumnCount(int32_t* aColumnCount) {
+ NS_ENSURE_ARG_POINTER(aColumnCount);
+ *aColumnCount = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aColumnCount = Intl()->ColCount();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetRowCount(int32_t* aRowCount) {
+ NS_ENSURE_ARG_POINTER(aRowCount);
+ *aRowCount = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aRowCount = Intl()->RowCount();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetCellAt(int32_t aRowIdx, int32_t aColIdx,
+ nsIAccessible** aCell) {
+ NS_ENSURE_ARG_POINTER(aCell);
+ *aCell = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= Intl()->RowCount() ||
+ aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ NS_IF_ADDREF(*aCell = ToXPC(Intl()->CellAt(aRowIdx, aColIdx)));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetCellIndexAt(int32_t aRowIdx, int32_t aColIdx,
+ int32_t* aCellIdx) {
+ NS_ENSURE_ARG_POINTER(aCellIdx);
+ *aCellIdx = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= Intl()->RowCount() ||
+ aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *aCellIdx = Intl()->CellIndexAt(aRowIdx, aColIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetColumnExtentAt(int32_t aRowIdx, int32_t aColIdx,
+ int32_t* aColumnExtent) {
+ NS_ENSURE_ARG_POINTER(aColumnExtent);
+ *aColumnExtent = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= Intl()->RowCount() ||
+ aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *aColumnExtent = Intl()->ColExtentAt(aRowIdx, aColIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetRowExtentAt(int32_t aRowIdx, int32_t aColIdx,
+ int32_t* aRowExtent) {
+ NS_ENSURE_ARG_POINTER(aRowExtent);
+ *aRowExtent = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= Intl()->RowCount() ||
+ aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *aRowExtent = Intl()->RowExtentAt(aRowIdx, aColIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetColumnDescription(int32_t aColIdx,
+ nsAString& aDescription) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsAutoString description;
+ Intl()->ColDescription(aColIdx, description);
+ aDescription.Assign(description);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetRowDescription(int32_t aRowIdx,
+ nsAString& aDescription) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsAutoString description;
+ Intl()->RowDescription(aRowIdx, description);
+ aDescription.Assign(description);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::IsColumnSelected(int32_t aColIdx, bool* aIsSelected) {
+ NS_ENSURE_ARG_POINTER(aIsSelected);
+ *aIsSelected = false;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *aIsSelected = Intl()->IsColSelected(aColIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::IsRowSelected(int32_t aRowIdx, bool* aIsSelected) {
+ NS_ENSURE_ARG_POINTER(aIsSelected);
+ *aIsSelected = false;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= Intl()->RowCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *aIsSelected = Intl()->IsRowSelected(aRowIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::IsCellSelected(int32_t aRowIdx, int32_t aColIdx,
+ bool* aIsSelected) {
+ NS_ENSURE_ARG_POINTER(aIsSelected);
+ *aIsSelected = false;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= Intl()->RowCount() ||
+ aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *aIsSelected = Intl()->IsCellSelected(aRowIdx, aColIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetSelectedCellCount(uint32_t* aSelectedCellCount) {
+ NS_ENSURE_ARG_POINTER(aSelectedCellCount);
+ *aSelectedCellCount = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aSelectedCellCount = Intl()->SelectedCellCount();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetSelectedColumnCount(uint32_t* aSelectedColumnCount) {
+ NS_ENSURE_ARG_POINTER(aSelectedColumnCount);
+ *aSelectedColumnCount = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aSelectedColumnCount = Intl()->SelectedColCount();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetSelectedRowCount(uint32_t* aSelectedRowCount) {
+ NS_ENSURE_ARG_POINTER(aSelectedRowCount);
+ *aSelectedRowCount = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aSelectedRowCount = Intl()->SelectedRowCount();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetSelectedCells(nsIArray** aSelectedCells) {
+ NS_ENSURE_ARG_POINTER(aSelectedCells);
+ *aSelectedCells = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMutableArray> selCells =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ AutoTArray<Accessible*, XPC_TABLE_DEFAULT_SIZE> cellsArray;
+ Intl()->SelectedCells(&cellsArray);
+
+ uint32_t totalCount = cellsArray.Length();
+ for (uint32_t idx = 0; idx < totalCount; idx++) {
+ Accessible* cell = cellsArray.ElementAt(idx);
+ selCells->AppendElement(static_cast<nsIAccessible*>(ToXPC(cell)));
+ }
+
+ NS_ADDREF(*aSelectedCells = selCells);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetSelectedCellIndices(nsTArray<uint32_t>& aCellsArray) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->SelectedCellIndices(&aCellsArray);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetSelectedColumnIndices(nsTArray<uint32_t>& aColsArray) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->SelectedColIndices(&aColsArray);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetSelectedRowIndices(nsTArray<uint32_t>& aRowsArray) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->SelectedRowIndices(&aRowsArray);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetColumnIndexAt(int32_t aCellIdx, int32_t* aColIdx) {
+ NS_ENSURE_ARG_POINTER(aColIdx);
+ *aColIdx = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aCellIdx < 0 || static_cast<uint32_t>(aCellIdx) >=
+ Intl()->RowCount() * Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *aColIdx = Intl()->ColIndexAt(aCellIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetRowIndexAt(int32_t aCellIdx, int32_t* aRowIdx) {
+ NS_ENSURE_ARG_POINTER(aRowIdx);
+ *aRowIdx = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aCellIdx < 0 || static_cast<uint32_t>(aCellIdx) >=
+ Intl()->RowCount() * Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ *aRowIdx = Intl()->RowIndexAt(aCellIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetRowAndColumnIndicesAt(int32_t aCellIdx, int32_t* aRowIdx,
+ int32_t* aColIdx) {
+ NS_ENSURE_ARG_POINTER(aRowIdx);
+ *aRowIdx = -1;
+ NS_ENSURE_ARG_POINTER(aColIdx);
+ *aColIdx = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aCellIdx < 0 || static_cast<uint32_t>(aCellIdx) >=
+ Intl()->RowCount() * Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ Intl()->RowAndColIndicesAt(aCellIdx, aRowIdx, aColIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::GetSummary(nsAString& aSummary) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ nsAutoString summary;
+ Intl()->Summary(summary);
+ aSummary.Assign(summary);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::IsProbablyForLayout(bool* aResult) {
+ NS_ENSURE_ARG_POINTER(aResult);
+ *aResult = false;
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aResult = Intl()->IsProbablyLayoutTable();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::SelectColumn(int32_t aColIdx) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ Intl()->SelectCol(aColIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::SelectRow(int32_t aRowIdx) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= Intl()->RowCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ Intl()->SelectRow(aRowIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::UnselectColumn(int32_t aColIdx) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aColIdx < 0 || static_cast<uint32_t>(aColIdx) >= Intl()->ColCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ Intl()->UnselectCol(aColIdx);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTable::UnselectRow(int32_t aRowIdx) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (aRowIdx < 0 || static_cast<uint32_t>(aRowIdx) >= Intl()->RowCount()) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ Intl()->UnselectRow(aRowIdx);
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleTable.h b/accessible/xpcom/xpcAccessibleTable.h
new file mode 100644
index 0000000000..5cdb5e5b3f
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTable.h
@@ -0,0 +1,78 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleTable_h_
+#define mozilla_a11y_xpcAccessibleTable_h_
+
+#include "nsIAccessibleTable.h"
+#include "xpcAccessibleHyperText.h"
+
+namespace mozilla {
+namespace a11y {
+class TableAccessibleBase;
+
+/**
+ * XPCOM wrapper around TableAccessible class.
+ */
+class xpcAccessibleTable : public xpcAccessibleHyperText,
+ public nsIAccessibleTable {
+ public:
+ explicit xpcAccessibleTable(Accessible* aIntl)
+ : xpcAccessibleHyperText(aIntl) {}
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIAccessibleTable
+ NS_IMETHOD GetCaption(nsIAccessible** aCaption) final;
+ NS_IMETHOD GetSummary(nsAString& aSummary) final;
+ NS_IMETHOD GetColumnCount(int32_t* aColumnCount) final;
+ NS_IMETHOD GetRowCount(int32_t* aRowCount) final;
+ NS_IMETHOD GetCellAt(int32_t aRowIndex, int32_t aColumnIndex,
+ nsIAccessible** aCell) final;
+ NS_IMETHOD GetCellIndexAt(int32_t aRowIndex, int32_t aColumnIndex,
+ int32_t* aCellIndex) final;
+ NS_IMETHOD GetColumnIndexAt(int32_t aCellIndex, int32_t* aColumnIndex) final;
+ NS_IMETHOD GetRowIndexAt(int32_t aCellIndex, int32_t* aRowIndex) final;
+ NS_IMETHOD GetRowAndColumnIndicesAt(int32_t aCellIndex, int32_t* aRowIndex,
+ int32_t* aColumnIndex) final;
+ NS_IMETHOD GetColumnExtentAt(int32_t row, int32_t column,
+ int32_t* aColumnExtent) final;
+ NS_IMETHOD GetRowExtentAt(int32_t row, int32_t column,
+ int32_t* aRowExtent) final;
+ NS_IMETHOD GetColumnDescription(int32_t aColIdx,
+ nsAString& aDescription) final;
+ NS_IMETHOD GetRowDescription(int32_t aRowIdx, nsAString& aDescription) final;
+ NS_IMETHOD IsColumnSelected(int32_t aColIdx, bool* _retval) final;
+ NS_IMETHOD IsRowSelected(int32_t aRowIdx, bool* _retval) final;
+ NS_IMETHOD IsCellSelected(int32_t aRowIdx, int32_t aColIdx,
+ bool* _retval) final;
+ NS_IMETHOD GetSelectedCellCount(uint32_t* aSelectedCellCount) final;
+ NS_IMETHOD GetSelectedColumnCount(uint32_t* aSelectedColumnCount) final;
+ NS_IMETHOD GetSelectedRowCount(uint32_t* aSelectedRowCount) final;
+ NS_IMETHOD GetSelectedCells(nsIArray** aSelectedCell) final;
+ NS_IMETHOD GetSelectedCellIndices(nsTArray<uint32_t>& aCellsArray) final;
+ NS_IMETHOD GetSelectedColumnIndices(nsTArray<uint32_t>& aColsArray) final;
+ NS_IMETHOD GetSelectedRowIndices(nsTArray<uint32_t>& aRowsArray) final;
+ NS_IMETHOD SelectColumn(int32_t aColIdx) final;
+ NS_IMETHOD SelectRow(int32_t aRowIdx) final;
+ NS_IMETHOD UnselectColumn(int32_t aColIdx) final;
+ NS_IMETHOD UnselectRow(int32_t aRowIdx) final;
+ NS_IMETHOD IsProbablyForLayout(bool* aIsForLayout) final;
+
+ protected:
+ virtual ~xpcAccessibleTable() {}
+
+ private:
+ TableAccessibleBase* Intl() { return mIntl->AsTableBase(); }
+
+ xpcAccessibleTable(const xpcAccessibleTable&) = delete;
+ xpcAccessibleTable& operator=(const xpcAccessibleTable&) = delete;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // mozilla_a11y_xpcAccessibleTable_h_
diff --git a/accessible/xpcom/xpcAccessibleTableCell.cpp b/accessible/xpcom/xpcAccessibleTableCell.cpp
new file mode 100644
index 0000000000..2577e63e8c
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTableCell.cpp
@@ -0,0 +1,141 @@
+/* -*- 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 "xpcAccessibleTableCell.h"
+
+#include "mozilla/a11y/Accessible.h"
+#include "mozilla/a11y/TableAccessibleBase.h"
+#include "mozilla/a11y/TableCellAccessibleBase.h"
+#include "nsIAccessibleTable.h"
+
+#include "nsComponentManagerUtils.h"
+#include "nsIMutableArray.h"
+#include "xpcAccessibleDocument.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+NS_IMPL_ISUPPORTS_INHERITED(xpcAccessibleTableCell, xpcAccessibleHyperText,
+ nsIAccessibleTableCell)
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleTableCell
+
+NS_IMETHODIMP
+xpcAccessibleTableCell::GetTable(nsIAccessibleTable** aTable) {
+ NS_ENSURE_ARG_POINTER(aTable);
+ *aTable = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ TableAccessibleBase* table = Intl()->Table();
+ if (!table) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIAccessibleTable> xpcTable = do_QueryInterface(
+ static_cast<nsIAccessible*>(ToXPC(table->AsAccessible())));
+ xpcTable.forget(aTable);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTableCell::GetColumnIndex(int32_t* aColIdx) {
+ NS_ENSURE_ARG_POINTER(aColIdx);
+ *aColIdx = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aColIdx = Intl()->ColIdx();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTableCell::GetRowIndex(int32_t* aRowIdx) {
+ NS_ENSURE_ARG_POINTER(aRowIdx);
+ *aRowIdx = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aRowIdx = Intl()->RowIdx();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTableCell::GetColumnExtent(int32_t* aExtent) {
+ NS_ENSURE_ARG_POINTER(aExtent);
+ *aExtent = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aExtent = Intl()->ColExtent();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTableCell::GetRowExtent(int32_t* aExtent) {
+ NS_ENSURE_ARG_POINTER(aExtent);
+ *aExtent = -1;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aExtent = Intl()->RowExtent();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTableCell::GetColumnHeaderCells(nsIArray** aHeaderCells) {
+ NS_ENSURE_ARG_POINTER(aHeaderCells);
+ *aHeaderCells = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ AutoTArray<Accessible*, 10> headerCells;
+ Intl()->ColHeaderCells(&headerCells);
+
+ nsCOMPtr<nsIMutableArray> cells = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ NS_ENSURE_TRUE(cells, NS_ERROR_FAILURE);
+
+ for (uint32_t idx = 0; idx < headerCells.Length(); idx++) {
+ cells->AppendElement(static_cast<nsIAccessible*>(ToXPC(headerCells[idx])));
+ }
+
+ NS_ADDREF(*aHeaderCells = cells);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTableCell::GetRowHeaderCells(nsIArray** aHeaderCells) {
+ NS_ENSURE_ARG_POINTER(aHeaderCells);
+ *aHeaderCells = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ AutoTArray<Accessible*, 10> headerCells;
+ Intl()->RowHeaderCells(&headerCells);
+
+ nsCOMPtr<nsIMutableArray> cells = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ NS_ENSURE_TRUE(cells, NS_ERROR_FAILURE);
+
+ for (uint32_t idx = 0; idx < headerCells.Length(); idx++) {
+ cells->AppendElement(static_cast<nsIAccessible*>(ToXPC(headerCells[idx])));
+ }
+
+ NS_ADDREF(*aHeaderCells = cells);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTableCell::IsSelected(bool* aSelected) {
+ NS_ENSURE_ARG_POINTER(aSelected);
+ *aSelected = false;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ *aSelected = Intl()->Selected();
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleTableCell.h b/accessible/xpcom/xpcAccessibleTableCell.h
new file mode 100644
index 0000000000..b0f1ebb547
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTableCell.h
@@ -0,0 +1,52 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcom_xpcAccessibletableCell_h_
+#define mozilla_a11y_xpcom_xpcAccessibletableCell_h_
+
+#include "nsIAccessibleTable.h"
+
+#include "xpcAccessibleHyperText.h"
+
+namespace mozilla {
+namespace a11y {
+class TableCellAccessibleBase;
+
+/**
+ * XPCOM wrapper around TableAccessibleCell class.
+ */
+class xpcAccessibleTableCell : public xpcAccessibleHyperText,
+ public nsIAccessibleTableCell {
+ public:
+ explicit xpcAccessibleTableCell(Accessible* aIntl)
+ : xpcAccessibleHyperText(aIntl) {}
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ // nsIAccessibleTableCell
+ NS_IMETHOD GetTable(nsIAccessibleTable** aTable) final;
+ NS_IMETHOD GetColumnIndex(int32_t* aColIdx) final;
+ NS_IMETHOD GetRowIndex(int32_t* aRowIdx) final;
+ NS_IMETHOD GetColumnExtent(int32_t* aExtent) final;
+ NS_IMETHOD GetRowExtent(int32_t* aExtent) final;
+ NS_IMETHOD GetColumnHeaderCells(nsIArray** aHeaderCells) final;
+ NS_IMETHOD GetRowHeaderCells(nsIArray** aHeaderCells) final;
+ NS_IMETHOD IsSelected(bool* aSelected) final;
+
+ protected:
+ virtual ~xpcAccessibleTableCell() {}
+
+ private:
+ TableCellAccessibleBase* Intl() { return mIntl->AsTableCellBase(); }
+
+ xpcAccessibleTableCell(const xpcAccessibleTableCell&) = delete;
+ xpcAccessibleTableCell& operator=(const xpcAccessibleTableCell&) = delete;
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif // mozilla_a11y_xpcom_xpcAccessibletableCell_h_
diff --git a/accessible/xpcom/xpcAccessibleTextRange.cpp b/accessible/xpcom/xpcAccessibleTextRange.cpp
new file mode 100644
index 0000000000..761f3559b7
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTextRange.cpp
@@ -0,0 +1,159 @@
+/* -*- 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 "xpcAccessibleTextRange.h"
+
+#include "TextRange-inl.h"
+
+#include "nsIMutableArray.h"
+#include "nsComponentManagerUtils.h"
+#include "nsQueryObject.h"
+#include "xpcAccessibleDocument.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+// nsISupports and cycle collection
+
+NS_INTERFACE_MAP_BEGIN(xpcAccessibleTextRange)
+ NS_INTERFACE_MAP_ENTRY(nsIAccessibleTextRange)
+ NS_INTERFACE_MAP_ENTRY(xpcAccessibleTextRange)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleTextRange)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(xpcAccessibleTextRange)
+NS_IMPL_RELEASE(xpcAccessibleTextRange)
+
+a11y::TextRange xpcAccessibleTextRange::Range() {
+ return a11y::TextRange(mRoot->ToInternalGeneric(),
+ mStartContainer->ToInternalGeneric(), mStartOffset,
+ mEndContainer->ToInternalGeneric(), mEndOffset);
+}
+
+void xpcAccessibleTextRange::SetRange(TextRange& aRange) {
+ mRoot = ToXPCText(aRange.Root());
+ mStartContainer = ToXPCText(aRange.StartContainer());
+ mStartOffset = aRange.StartOffset();
+ mEndContainer = ToXPCText(aRange.EndContainer());
+ mEndOffset = aRange.EndOffset();
+}
+
+// nsIAccessibleTextRange
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetStartContainer(nsIAccessibleText** aAnchor) {
+ NS_ENSURE_ARG_POINTER(aAnchor);
+ NS_IF_ADDREF(*aAnchor = mStartContainer);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetStartOffset(int32_t* aOffset) {
+ NS_ENSURE_ARG_POINTER(aOffset);
+ *aOffset = mStartOffset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetEndContainer(nsIAccessibleText** aAnchor) {
+ NS_ENSURE_ARG_POINTER(aAnchor);
+ NS_IF_ADDREF(*aAnchor = mEndContainer);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetEndOffset(int32_t* aOffset) {
+ NS_ENSURE_ARG_POINTER(aOffset);
+ *aOffset = mEndOffset;
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetContainer(nsIAccessible** aContainer) {
+ NS_ENSURE_ARG_POINTER(aContainer);
+ NS_IF_ADDREF(*aContainer = ToXPC(Range().Container()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetEmbeddedChildren(nsIArray** aList) {
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIMutableArray> xpcList =
+ do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsTArray<Accessible*> objects;
+ Range().EmbeddedChildren(&objects);
+
+ uint32_t len = objects.Length();
+ for (uint32_t idx = 0; idx < len; idx++) {
+ xpcList->AppendElement(static_cast<nsIAccessible*>(ToXPC(objects[idx])));
+ }
+
+ xpcList.forget(aList);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::Compare(nsIAccessibleTextRange* aOtherRange,
+ bool* aResult) {
+ RefPtr<xpcAccessibleTextRange> xpcRange(do_QueryObject(aOtherRange));
+ if (!xpcRange || !aResult) return NS_ERROR_INVALID_ARG;
+
+ *aResult = (Range() == xpcRange->Range());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::CompareEndPoints(uint32_t aEndPoint,
+ nsIAccessibleTextRange* aOtherRange,
+ uint32_t aOtherRangeEndPoint,
+ int32_t* aResult) {
+ RefPtr<xpcAccessibleTextRange> xpcRange(do_QueryObject(aOtherRange));
+ if (!xpcRange || !aResult) return NS_ERROR_INVALID_ARG;
+
+ TextRange thisRange = Range();
+ TextRange otherRange = xpcRange->Range();
+ TextPoint p = (aEndPoint == EndPoint_Start) ? thisRange.StartPoint()
+ : thisRange.EndPoint();
+ TextPoint otherPoint = (aOtherRangeEndPoint == EndPoint_Start)
+ ? otherRange.StartPoint()
+ : otherRange.EndPoint();
+
+ if (p == otherPoint) {
+ *aResult = 0;
+ } else {
+ *aResult = p < otherPoint ? -1 : 1;
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetText(nsAString& aText) {
+ nsAutoString text;
+ Range().Text(text);
+ aText.Assign(text);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::Crop(nsIAccessible* aContainer, bool* aSuccess) {
+ Accessible* container = aContainer->ToInternalGeneric();
+ NS_ENSURE_TRUE(container, NS_ERROR_INVALID_ARG);
+
+ TextRange range = Range();
+ *aSuccess = range.Crop(container);
+ if (*aSuccess) {
+ SetRange(range);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::ScrollIntoView(uint32_t aHow) { return NS_OK; }
diff --git a/accessible/xpcom/xpcAccessibleTextRange.h b/accessible/xpcom/xpcAccessibleTextRange.h
new file mode 100644
index 0000000000..e9cc5caf03
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTextRange.h
@@ -0,0 +1,81 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleTextRange_h_
+#define mozilla_a11y_xpcAccessibleTextRange_h_
+
+#include <utility>
+
+#include "TextRange.h"
+#include "nsIAccessibleTextRange.h"
+#include "xpcAccessibleHyperText.h"
+
+namespace mozilla {
+namespace a11y {
+
+class TextRange;
+
+#define NS_ACCESSIBLETEXTRANGE_IMPL_IID \
+ { /* 133c8bf4-4913-4355-bd50-426bd1d6e1ad */ \
+ 0xb17652d9, 0x4f54, 0x4c56, { \
+ 0xbb, 0x62, 0x6d, 0x5b, 0xf1, 0xef, 0x91, 0x0c \
+ } \
+ }
+
+class xpcAccessibleTextRange final : public nsIAccessibleTextRange {
+ public:
+ explicit xpcAccessibleTextRange(TextRange& aRange) { SetRange(aRange); }
+
+ NS_DECL_ISUPPORTS
+
+ NS_IMETHOD GetStartContainer(nsIAccessibleText** aAnchor) final;
+ NS_IMETHOD GetStartOffset(int32_t* aOffset) final;
+ NS_IMETHOD GetEndContainer(nsIAccessibleText** aAnchor) final;
+ NS_IMETHOD GetEndOffset(int32_t* aOffset) final;
+ NS_IMETHOD GetContainer(nsIAccessible** aContainer) final;
+ NS_IMETHOD GetEmbeddedChildren(nsIArray** aList) final;
+ NS_IMETHOD Compare(nsIAccessibleTextRange* aOtherRange, bool* aResult) final;
+ NS_IMETHOD CompareEndPoints(uint32_t aEndPoint,
+ nsIAccessibleTextRange* aOtherRange,
+ uint32_t aOtherRangeEndPoint,
+ int32_t* aResult) final;
+ NS_IMETHOD GetText(nsAString& aText) final;
+ NS_IMETHOD Crop(nsIAccessible* aContainer, bool* aSuccess) final;
+ NS_IMETHOD ScrollIntoView(uint32_t aHow) final;
+
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLETEXTRANGE_IMPL_IID)
+
+ private:
+ xpcAccessibleTextRange() {}
+
+ ~xpcAccessibleTextRange() {}
+
+ friend class xpcAccessibleHyperText;
+
+ xpcAccessibleTextRange& operator=(const xpcAccessibleTextRange&) = delete;
+
+ void SetRange(TextRange& aRange);
+
+ TextRange Range();
+
+ // We can't hold a strong reference to an Accessible, but XPCOM needs strong
+ // references. Thus, instead of holding a TextRange here, we hold
+ // xpcAccessibleHyperText references and create the TextRange for each call
+ // using Range().
+ RefPtr<xpcAccessibleHyperText> mRoot;
+ RefPtr<xpcAccessibleHyperText> mStartContainer;
+ int32_t mStartOffset;
+ RefPtr<xpcAccessibleHyperText> mEndContainer;
+ int32_t mEndOffset;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(xpcAccessibleTextRange,
+ NS_ACCESSIBLETEXTRANGE_IMPL_IID)
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleValue.cpp b/accessible/xpcom/xpcAccessibleValue.cpp
new file mode 100644
index 0000000000..495e841848
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleValue.cpp
@@ -0,0 +1,101 @@
+/* -*- 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 "xpcAccessibleGeneric.h"
+#include "LocalAccessible.h"
+#include "LocalAccessible-inl.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetMaximumValue(double* aValue) {
+ NS_ENSURE_ARG_POINTER(aValue);
+ *aValue = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (Intl()->IsLocal() && Intl()->AsLocal()->IsDefunct()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ double value = Intl()->MaxValue();
+
+ if (!IsNaN(value)) *aValue = value;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetMinimumValue(double* aValue) {
+ NS_ENSURE_ARG_POINTER(aValue);
+ *aValue = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (Intl()->IsLocal() && Intl()->AsLocal()->IsDefunct()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ double value = Intl()->MinValue();
+
+ if (!IsNaN(value)) *aValue = value;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetCurrentValue(double* aValue) {
+ NS_ENSURE_ARG_POINTER(aValue);
+ *aValue = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (Intl()->IsLocal() && Intl()->AsLocal()->IsDefunct()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ double value = Intl()->CurValue();
+
+ if (!IsNaN(value)) *aValue = value;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::SetCurrentValue(double aValue) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (Intl()->IsLocal() && Intl()->AsLocal()->IsDefunct()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (Intl()->IsLocal()) {
+ Intl()->AsLocal()->SetCurValue(aValue);
+ } else {
+ Intl()->AsRemote()->SetCurValue(aValue);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetMinimumIncrement(double* aValue) {
+ NS_ENSURE_ARG_POINTER(aValue);
+ *aValue = 0;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ if (Intl()->IsLocal() && Intl()->AsLocal()->IsDefunct()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ double value = Intl()->Step();
+
+ if (!IsNaN(value)) *aValue = value;
+
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleValue.h b/accessible/xpcom/xpcAccessibleValue.h
new file mode 100644
index 0000000000..812278ab56
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleValue.h
@@ -0,0 +1,42 @@
+/* -*- 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibleValue_h_
+#define mozilla_a11y_xpcAccessibleValue_h_
+
+#include "nsIAccessibleValue.h"
+
+namespace mozilla {
+namespace a11y {
+
+class LocalAccessible;
+
+/**
+ * XPCOM nsIAccessibleValue interface implementation, used by
+ * xpcAccessibleGeneric class.
+ */
+class xpcAccessibleValue : public nsIAccessibleValue {
+ public:
+ NS_IMETHOD GetMaximumValue(double* aValue) final;
+ NS_IMETHOD GetMinimumValue(double* aValue) final;
+ NS_IMETHOD GetCurrentValue(double* aValue) final;
+ NS_IMETHOD SetCurrentValue(double aValue) final;
+ NS_IMETHOD GetMinimumIncrement(double* aMinIncrement) final;
+
+ protected:
+ xpcAccessibleValue() {}
+ virtual ~xpcAccessibleValue() {}
+
+ private:
+ Accessible* Intl();
+
+ xpcAccessibleValue(const xpcAccessibleValue&) = delete;
+ xpcAccessibleValue& operator=(const xpcAccessibleValue&) = delete;
+};
+
+} // namespace a11y
+} // namespace mozilla
+#endif