summaryrefslogtreecommitdiffstats
path: root/accessible/xpcom
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /accessible/xpcom
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'accessible/xpcom')
-rwxr-xr-xaccessible/xpcom/AccEventGen.py258
-rw-r--r--accessible/xpcom/AccEvents.conf21
-rw-r--r--accessible/xpcom/moz.build81
-rw-r--r--accessible/xpcom/nsAccessibleRelation.cpp69
-rw-r--r--accessible/xpcom/nsAccessibleRelation.h49
-rw-r--r--accessible/xpcom/xpcAccessibilityService.cpp270
-rw-r--r--accessible/xpcom/xpcAccessibilityService.h68
-rw-r--r--accessible/xpcom/xpcAccessible.cpp815
-rw-r--r--accessible/xpcom/xpcAccessible.h109
-rw-r--r--accessible/xpcom/xpcAccessibleApplication.cpp60
-rw-r--r--accessible/xpcom/xpcAccessibleApplication.h49
-rw-r--r--accessible/xpcom/xpcAccessibleDocument.cpp234
-rw-r--r--accessible/xpcom/xpcAccessibleDocument.h144
-rw-r--r--accessible/xpcom/xpcAccessibleGeneric.cpp61
-rw-r--r--accessible/xpcom/xpcAccessibleGeneric.h94
-rw-r--r--accessible/xpcom/xpcAccessibleHyperLink.cpp163
-rw-r--r--accessible/xpcom/xpcAccessibleHyperLink.h48
-rw-r--r--accessible/xpcom/xpcAccessibleHyperText.cpp744
-rw-r--r--accessible/xpcom/xpcAccessibleHyperText.h61
-rw-r--r--accessible/xpcom/xpcAccessibleImage.cpp51
-rw-r--r--accessible/xpcom/xpcAccessibleImage.h47
-rw-r--r--accessible/xpcom/xpcAccessibleMacInterface.h108
-rw-r--r--accessible/xpcom/xpcAccessibleMacInterface.mm509
-rw-r--r--accessible/xpcom/xpcAccessibleSelectable.cpp120
-rw-r--r--accessible/xpcom/xpcAccessibleSelectable.h50
-rw-r--r--accessible/xpcom/xpcAccessibleTable.cpp395
-rw-r--r--accessible/xpcom/xpcAccessibleTable.h82
-rw-r--r--accessible/xpcom/xpcAccessibleTableCell.cpp141
-rw-r--r--accessible/xpcom/xpcAccessibleTableCell.h60
-rw-r--r--accessible/xpcom/xpcAccessibleTextRange.cpp182
-rw-r--r--accessible/xpcom/xpcAccessibleTextRange.h85
-rw-r--r--accessible/xpcom/xpcAccessibleValue.cpp115
-rw-r--r--accessible/xpcom/xpcAccessibleValue.h42
33 files changed, 5385 insertions, 0 deletions
diff --git a/accessible/xpcom/AccEventGen.py b/accessible/xpcom/AccEventGen.py
new file mode 100755
index 0000000000..ef253bd2a9
--- /dev/null
+++ b/accessible/xpcom/AccEventGen.py
@@ -0,0 +1,258 @@
+#!/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/.
+
+from __future__ import absolute_import
+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..f45f3abcb2
--- /dev/null
+++ b/accessible/xpcom/moz.build
@@ -0,0 +1,81 @@
+# -*- 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/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")
+
+if CONFIG["CC_TYPE"] in ("clang", "gcc"):
+ CXXFLAGS += ["-Wno-error=shadow"]
diff --git a/accessible/xpcom/nsAccessibleRelation.cpp b/accessible/xpcom/nsAccessibleRelation.cpp
new file mode 100644
index 0000000000..933a394689
--- /dev/null
+++ b/accessible/xpcom/nsAccessibleRelation.cpp
@@ -0,0 +1,69 @@
+/* -*- 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 "Accessible.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(
+ uint32_t aType, const nsTArray<ProxyAccessible*>* aTargets)
+ : mType(aType) {
+ mTargets = do_CreateInstance(NS_ARRAY_CONTRACTID);
+ for (uint32_t idx = 0; idx < aTargets->Length(); ++idx) {
+ mTargets->AppendElement(
+ static_cast<nsIAccessible*>(ToXPC(aTargets->ElementAt(idx))));
+ }
+}
+
+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..ff51c33cd9
--- /dev/null
+++ b/accessible/xpcom/nsAccessibleRelation.h
@@ -0,0 +1,49 @@
+/* -*- 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/ProxyAccessible.h"
+
+namespace mozilla {
+namespace a11y {
+
+class Relation;
+
+/**
+ * Class represents an accessible relation.
+ */
+class nsAccessibleRelation final : public nsIAccessibleRelation {
+ public:
+ nsAccessibleRelation(uint32_t aType, Relation* aRel);
+
+ nsAccessibleRelation(uint32_t aType,
+ const nsTArray<ProxyAccessible*>* aTargets);
+
+ 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..7362eb3ded
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibilityService.cpp
@@ -0,0 +1,270 @@
+/* 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 "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::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.
+ Accessible* 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;
+
+ Accessible* 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();
+ NS_ENSURE_TRUE(service, NS_ERROR_OUT_OF_MEMORY);
+ 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..f3590a4ddc
--- /dev/null
+++ b/accessible/xpcom/xpcAccessible.cpp
@@ -0,0 +1,815 @@
+/* -*- 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-inl.h"
+#include "mozilla/a11y/DocAccessibleParent.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().IsNull()) return NS_ERROR_FAILURE;
+
+ AccessibleOrProxy 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().IsNull()) return NS_ERROR_FAILURE;
+
+ if (IntlGeneric().IsAccessible()) {
+ nsresult rv = NS_OK;
+ NS_IF_ADDREF(*aNextSibling = ToXPC(Intl()->GetSiblingAtOffset(1, &rv)));
+ return rv;
+ }
+
+ ProxyAccessible* proxy = IntlGeneric().AsProxy();
+ NS_ENSURE_STATE(proxy);
+
+ NS_IF_ADDREF(*aNextSibling = ToXPC(proxy->NextSibling()));
+ return *aNextSibling ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetPreviousSibling(nsIAccessible** aPreviousSibling) {
+ NS_ENSURE_ARG_POINTER(aPreviousSibling);
+ *aPreviousSibling = nullptr;
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (IntlGeneric().IsAccessible()) {
+ nsresult rv = NS_OK;
+ NS_IF_ADDREF(*aPreviousSibling =
+ ToXPC(Intl()->GetSiblingAtOffset(-1, &rv)));
+ return rv;
+ }
+
+ ProxyAccessible* proxy = IntlGeneric().AsProxy();
+ NS_ENSURE_STATE(proxy);
+
+ NS_IF_ADDREF(*aPreviousSibling = ToXPC(proxy->PrevSibling()));
+ return *aPreviousSibling ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetFirstChild(nsIAccessible** aFirstChild) {
+ NS_ENSURE_ARG_POINTER(aFirstChild);
+ *aFirstChild = nullptr;
+
+ if (IntlGeneric().IsNull()) 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().IsNull()) 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().IsNull()) 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().IsNull()) 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;
+
+ AccessibleOrProxy child = IntlGeneric().ChildAt(aChildIndex);
+ if (child.IsNull()) 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().IsNull()) 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++) {
+ AccessibleOrProxy 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().IsNull()) return NS_ERROR_FAILURE;
+
+ if (IntlGeneric().IsAccessible()) {
+ *aIndexInParent = Intl()->IndexInParent();
+ } else if (IntlGeneric().IsProxy()) {
+ *aIndexInParent = IntlGeneric().AsProxy()->IndexInParent();
+ }
+
+ return *aIndexInParent != -1 ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetUniqueID(int64_t* aUniqueID) {
+ NS_ENSURE_ARG_POINTER(aUniqueID);
+
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (IntlGeneric().IsAccessible()) {
+ *aUniqueID = reinterpret_cast<uintptr_t>(Intl()->UniqueID());
+ } else if (IntlGeneric().IsProxy()) {
+ *aUniqueID = IntlGeneric().AsProxy()->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) {
+ ProxyAccessible* proxy = IntlGeneric().AsProxy();
+ 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().IsNull()) 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);
+
+ if (IntlGeneric().IsNull())
+ nsAccUtils::To32States(states::DEFUNCT, aState, aExtraState);
+ else if (Intl())
+ nsAccUtils::To32States(Intl()->State(), aState, aExtraState);
+ else
+ nsAccUtils::To32States(IntlGeneric().AsProxy()->State(), aState,
+ aExtraState);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetName(nsAString& aName) {
+ aName.Truncate();
+
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ nsAutoString name;
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+ proxy->Name(name);
+ } else {
+ Intl()->Name(name);
+ }
+
+ aName.Assign(name);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetDescription(nsAString& aDescription) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ nsAutoString desc;
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+ proxy->Description(desc);
+ } else {
+ Intl()->Description(desc);
+ }
+
+ aDescription.Assign(desc);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetLanguage(nsAString& aLanguage) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ nsAutoString lang;
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+ proxy->Language(lang);
+ } else {
+ Intl()->Language(lang);
+ }
+
+ aLanguage.Assign(lang);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetValue(nsAString& aValue) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ nsAutoString value;
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+ proxy->Value(value);
+ } else {
+ Intl()->Value(value);
+ }
+
+ aValue.Assign(value);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetHelp(nsAString& aHelp) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ nsAutoString help;
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#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().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ proxy->AccessKey().ToString(aAccessKey);
+#endif
+ } else {
+ Intl()->AccessKey().ToString(aAccessKey);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetKeyboardShortcut(nsAString& aKeyBinding) {
+ aKeyBinding.Truncate();
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ proxy->KeyboardShortcut().ToString(aKeyBinding);
+#endif
+ } else {
+ Intl()->KeyboardShortcut().ToString(aKeyBinding);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetAttributes(nsIPersistentProperties** aAttributes) {
+ NS_ENSURE_ARG_POINTER(aAttributes);
+ *aAttributes = nullptr;
+
+ if (IntlGeneric().IsNull()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (Accessible* acc = Intl()) {
+ nsCOMPtr<nsIPersistentProperties> attributes = acc->Attributes();
+ attributes.swap(*aAttributes);
+ return NS_OK;
+ }
+
+ ProxyAccessible* proxy = IntlGeneric().AsProxy();
+ AutoTArray<Attribute, 10> attrs;
+ proxy->Attributes(&attrs);
+
+ RefPtr<nsPersistentProperties> props = new nsPersistentProperties();
+ uint32_t attrCount = attrs.Length();
+ nsAutoString unused;
+ for (uint32_t i = 0; i < attrCount; i++) {
+ props->SetStringProperty(attrs[i].Name(), attrs[i].Value(), unused);
+ }
+
+ props.forget(aAttributes);
+ 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().IsNull()) return NS_ERROR_FAILURE;
+
+ nsIntRect rect;
+ if (Accessible* acc = IntlGeneric().AsAccessible()) {
+ rect = acc->Bounds();
+ } else {
+ rect = IntlGeneric().AsProxy()->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().IsNull()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsIntRect rect;
+ if (Accessible* acc = IntlGeneric().AsAccessible()) {
+ rect = acc->BoundsInCSSPixels();
+ } else {
+ rect = IntlGeneric().AsProxy()->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);
+ *aGroupLevel = 0;
+
+ NS_ENSURE_ARG_POINTER(aSimilarItemsInGroup);
+ *aSimilarItemsInGroup = 0;
+
+ NS_ENSURE_ARG_POINTER(aPositionInGroup);
+ *aPositionInGroup = 0;
+
+ GroupPos groupPos;
+ if (Accessible* acc = IntlGeneric().AsAccessible()) {
+ groupPos = acc->GroupPosition();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ groupPos = IntlGeneric().AsProxy()->GroupPosition();
+#endif
+ }
+
+ *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().IsNull()) return NS_ERROR_FAILURE;
+
+ if (IntlGeneric().IsAccessible()) {
+ Relation rel = Intl()->RelationByType(static_cast<RelationType>(aType));
+ NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &rel));
+ return NS_OK;
+ }
+
+ ProxyAccessible* proxy = IntlGeneric().AsProxy();
+ nsTArray<ProxyAccessible*> targets =
+ proxy->RelationByType(static_cast<RelationType>(aType));
+ NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &targets));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetRelations(nsIArray** aRelations) {
+ NS_ENSURE_ARG_POINTER(aRelations);
+ *aRelations = nullptr;
+
+ if (IntlGeneric().IsNull()) 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().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ NS_IF_ADDREF(*aChild = ToXPC(proxy->FocusedChild()));
+#endif
+ } else {
+ NS_IF_ADDREF(*aChild = ToXPC(Intl()->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().IsNull()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(IntlGeneric().ChildAtPoint(
+ aX, aY, Accessible::eDirectChild)));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetDeepestChildAtPoint(int32_t aX, int32_t aY,
+ nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(IntlGeneric().ChildAtPoint(
+ aX, aY, Accessible::eDeepestChild)));
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetDeepestChildAtPointInProcess(int32_t aX, int32_t aY,
+ nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+
+ AccessibleOrProxy generic = IntlGeneric();
+ if (generic.IsNull() || generic.IsProxy()) {
+ return NS_ERROR_FAILURE;
+ }
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(
+ Intl()->ChildAtPoint(aX, aY, Accessible::eDeepestChild)));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::SetSelected(bool aSelect) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ proxy->SetSelected(aSelect);
+#endif
+ } else {
+ Intl()->SetSelected(aSelect);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::TakeSelection() {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ proxy->TakeSelection();
+#endif
+ } else {
+ Intl()->TakeSelection();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::TakeFocus() {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+ proxy->TakeFocus();
+ } else {
+ Intl()->TakeFocus();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetActionCount(uint8_t* aActionCount) {
+ NS_ENSURE_ARG_POINTER(aActionCount);
+ *aActionCount = 0;
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ *aActionCount = proxy->ActionCount();
+#endif
+ } else {
+ *aActionCount = Intl()->ActionCount();
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetActionName(uint8_t aIndex, nsAString& aName) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsString name;
+ proxy->ActionNameAt(aIndex, name);
+ aName.Assign(name);
+#endif
+ } else {
+ if (aIndex >= Intl()->ActionCount()) return NS_ERROR_INVALID_ARG;
+
+ Intl()->ActionNameAt(aIndex, aName);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::GetActionDescription(uint8_t aIndex, nsAString& aDescription) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsString description;
+ proxy->ActionDescriptionAt(aIndex, description);
+ aDescription.Assign(description);
+#endif
+ } else {
+ if (aIndex >= Intl()->ActionCount()) return NS_ERROR_INVALID_ARG;
+
+ Intl()->ActionDescriptionAt(aIndex, aDescription);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::DoAction(uint8_t aIndex) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ return proxy->DoAction(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG;
+#endif
+ } else {
+ return Intl()->DoAction(aIndex) ? NS_OK : NS_ERROR_INVALID_ARG;
+ }
+}
+
+NS_IMETHODIMP
+xpcAccessible::ScrollTo(uint32_t aHow) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ proxy->ScrollTo(aHow);
+#endif
+ } else {
+ RefPtr<Accessible> intl = Intl();
+ intl->ScrollTo(aHow);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessible::ScrollToPoint(uint32_t aCoordinateType, int32_t aX, int32_t aY) {
+ if (IntlGeneric().IsNull()) return NS_ERROR_FAILURE;
+
+ if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#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 (ProxyAccessible* proxy = IntlGeneric().AsProxy()) {
+#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..6f1c964fc4
--- /dev/null
+++ b/accessible/xpcom/xpcAccessible.h
@@ -0,0 +1,109 @@
+/* -*- 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 AccessibleOrProxy;
+
+/**
+ * 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 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:
+ Accessible* Intl();
+ AccessibleOrProxy 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..d196004131
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleApplication.h
@@ -0,0 +1,49 @@
+/* -*- 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.AsAccessible()->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..e3dbe73f22
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleDocument.cpp
@@ -0,0 +1,234 @@
+/* -*- 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 "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.IsNull() && mCache.Count() == 0) {
+ if (mIntl.IsAccessible()) {
+ GetAccService()->RemoveFromXPCDocumentCache(
+ mIntl.AsAccessible()->AsDoc());
+ } else {
+ GetAccService()->RemoveFromRemoteXPCDocumentCache(
+ mIntl.AsProxy()->AsDoc());
+ }
+ }
+ return r;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleDocument
+
+NS_IMETHODIMP
+xpcAccessibleDocument::GetURL(nsAString& aURL) {
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Intl()->URL(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) {
+ MOZ_ASSERT(!mRemote);
+ if (ToXPCDocument(aAccessible->Document()) != this) {
+ NS_ERROR(
+ "This XPCOM document is not related with given internal accessible!");
+ return nullptr;
+ }
+
+ if (aAccessible->IsDoc()) return this;
+
+ xpcAccessibleGeneric* xpcAcc = mCache.Get(aAccessible);
+ if (xpcAcc) return xpcAcc;
+
+ if (aAccessible->IsImage())
+ xpcAcc = new xpcAccessibleImage(aAccessible);
+ else if (aAccessible->IsTable())
+ xpcAcc = new xpcAccessibleTable(aAccessible);
+ else if (aAccessible->IsTableCell())
+ xpcAcc = new xpcAccessibleTableCell(aAccessible);
+ else if (aAccessible->IsHyperText())
+ xpcAcc = new xpcAccessibleHyperText(aAccessible);
+ else
+ xpcAcc = new xpcAccessibleGeneric(aAccessible);
+
+ mCache.Put(aAccessible, xpcAcc);
+ return xpcAcc;
+}
+
+xpcAccessibleGeneric* xpcAccessibleDocument::GetXPCAccessible(
+ ProxyAccessible* aProxy) {
+ MOZ_ASSERT(mRemote);
+ MOZ_ASSERT(aProxy->Document() == mIntl.AsProxy());
+ if (aProxy->IsDoc()) {
+ return this;
+ }
+
+ xpcAccessibleGeneric* acc = mCache.Get(aProxy);
+ if (acc) {
+ return acc;
+ }
+
+ // XXX support exposing optional interfaces.
+ uint8_t interfaces = 0;
+ if (aProxy->mHasValue) {
+ interfaces |= eValue;
+ }
+
+ if (aProxy->mIsHyperLink) {
+ interfaces |= eHyperLink;
+ }
+
+ if (aProxy->mIsHyperText) {
+ interfaces |= eText;
+ acc = new xpcAccessibleHyperText(aProxy, interfaces);
+ mCache.Put(aProxy, acc);
+
+ return acc;
+ }
+
+ acc = new xpcAccessibleGeneric(aProxy, interfaces);
+ mCache.Put(aProxy, acc);
+
+ return acc;
+}
+
+void xpcAccessibleDocument::Shutdown() {
+ for (auto iter = mCache.Iter(); !iter.Done(); iter.Next()) {
+ iter.Data()->Shutdown();
+ iter.Remove();
+ }
+ xpcAccessibleGeneric::Shutdown();
+}
+
+xpcAccessibleGeneric* a11y::ToXPC(AccessibleOrProxy aAcc) {
+ if (aAcc.IsNull()) {
+ return nullptr;
+ }
+
+ if (aAcc.IsAccessible()) {
+ return ToXPC(aAcc.AsAccessible());
+ }
+
+ xpcAccessibleDocument* doc = ToXPCDocument(aAcc.AsProxy()->Document());
+ return doc->GetXPCAccessible(aAcc.AsProxy());
+}
diff --git a/accessible/xpcom/xpcAccessibleDocument.h b/accessible/xpcom/xpcAccessibleDocument.h
new file mode 100644
index 0000000000..f042cc1081
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleDocument.h
@@ -0,0 +1,144 @@
+/* -*- 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(DocAccessible* aIntl)
+ : xpcAccessibleHyperText(aIntl),
+ mCache(kDefaultCacheLength),
+ mRemote(false) {}
+
+ xpcAccessibleDocument(ProxyAccessible* aProxy, uint32_t aInterfaces)
+ : xpcAccessibleHyperText(aProxy, aInterfaces),
+ mCache(kDefaultCacheLength),
+ mRemote(true) {}
+
+ 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);
+ xpcAccessibleGeneric* GetXPCAccessible(ProxyAccessible* aProxy);
+
+ virtual void Shutdown() override;
+
+ protected:
+ virtual ~xpcAccessibleDocument() {}
+
+ private:
+ DocAccessible* Intl() {
+ if (Accessible* acc = mIntl.AsAccessible()) {
+ return acc->AsDoc();
+ }
+
+ return nullptr;
+ }
+
+ void NotifyOfShutdown(Accessible* aAccessible) {
+ MOZ_ASSERT(!mRemote);
+ xpcAccessibleGeneric* xpcAcc = mCache.Get(aAccessible);
+ if (xpcAcc) {
+ xpcAcc->Shutdown();
+ }
+
+ mCache.Remove(aAccessible);
+ if (mCache.Count() == 0 && mRefCnt == 1) {
+ GetAccService()->RemoveFromXPCDocumentCache(
+ mIntl.AsAccessible()->AsDoc());
+ }
+ }
+
+ void NotifyOfShutdown(ProxyAccessible* aProxy) {
+ MOZ_ASSERT(mRemote);
+ xpcAccessibleGeneric* xpcAcc = mCache.Get(aProxy);
+ if (xpcAcc) {
+ xpcAcc->Shutdown();
+ }
+
+ mCache.Remove(aProxy);
+ if (mCache.Count() == 0 && mRefCnt == 1) {
+ GetAccService()->RemoveFromRemoteXPCDocumentCache(
+ mIntl.AsProxy()->AsDoc());
+ }
+ }
+
+ friend class DocManager;
+ friend class DocAccessible;
+ friend class ProxyAccessible;
+ friend class ProxyAccessibleBase<ProxyAccessible>;
+ friend class xpcAccessibleGeneric;
+
+ xpcAccessibleDocument(const xpcAccessibleDocument&) = delete;
+ xpcAccessibleDocument& operator=(const xpcAccessibleDocument&) = delete;
+
+ nsDataHashtable<nsPtrHashKey<const void>, xpcAccessibleGeneric*> mCache;
+ bool mRemote;
+};
+
+inline xpcAccessibleGeneric* ToXPC(Accessible* aAccessible) {
+ if (!aAccessible) return nullptr;
+
+ if (aAccessible->IsApplication()) return XPCApplicationAcc();
+
+ xpcAccessibleDocument* xpcDoc =
+ GetAccService()->GetXPCDocument(aAccessible->Document());
+ return xpcDoc ? xpcDoc->GetAccessible(aAccessible) : nullptr;
+}
+
+xpcAccessibleGeneric* ToXPC(AccessibleOrProxy aAcc);
+
+inline xpcAccessibleHyperText* ToXPCText(HyperTextAccessible* aAccessible) {
+ if (!aAccessible) return nullptr;
+
+ xpcAccessibleDocument* xpcDoc =
+ GetAccService()->GetXPCDocument(aAccessible->Document());
+ return static_cast<xpcAccessibleHyperText*>(
+ xpcDoc->GetAccessible(aAccessible));
+}
+
+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..b615616353
--- /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.IsNull()) {
+ return;
+ }
+
+ xpcAccessibleDocument* xpcDoc = nullptr;
+ if (mIntl.IsAccessible()) {
+ Accessible* acc = mIntl.AsAccessible();
+ if (!acc->IsDoc() && !acc->IsApplication()) {
+ xpcDoc = GetAccService()->GetXPCDocument(acc->Document());
+ xpcDoc->NotifyOfShutdown(acc);
+ }
+ } else {
+ ProxyAccessible* proxy = mIntl.AsProxy();
+ if (!proxy->IsDoc()) {
+ xpcDoc = GetAccService()->GetXPCDocument(proxy->Document());
+ xpcDoc->NotifyOfShutdown(proxy);
+ }
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessible
+
+Accessible* xpcAccessibleGeneric::ToInternalAccessible() const {
+ return mIntl.AsAccessible();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// xpcAccessibleGeneric
+
+void xpcAccessibleGeneric::Shutdown() { mIntl = nullptr; }
diff --git a/accessible/xpcom/xpcAccessibleGeneric.h b/accessible/xpcom/xpcAccessibleGeneric.h
new file mode 100644
index 0000000000..499bdc8447
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleGeneric.h
@@ -0,0 +1,94 @@
+/* -*- 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 "Accessible.h"
+#include "AccessibleOrProxy.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;
+ }
+
+ xpcAccessibleGeneric(ProxyAccessible* aProxy, uint8_t aInterfaces)
+ : mIntl(aProxy), mSupportedIfaces(aInterfaces) {}
+
+ NS_DECL_ISUPPORTS
+
+ // nsIAccessible
+ Accessible* ToInternalAccessible() const final;
+
+ // xpcAccessibleGeneric
+ virtual void Shutdown();
+
+ protected:
+ virtual ~xpcAccessibleGeneric();
+
+ AccessibleOrProxy mIntl;
+
+ enum {
+ eSelectable = 1 << 0,
+ eValue = 1 << 1,
+ eHyperLink = 1 << 2,
+ eText = 1 << 3
+ };
+ uint8_t mSupportedIfaces;
+
+ private:
+ friend class Accessible;
+ friend class xpcAccessible;
+ friend class xpcAccessibleHyperLink;
+ friend class xpcAccessibleSelectable;
+ friend class xpcAccessibleValue;
+
+ xpcAccessibleGeneric(const xpcAccessibleGeneric&) = delete;
+ xpcAccessibleGeneric& operator=(const xpcAccessibleGeneric&) = delete;
+};
+
+inline Accessible* xpcAccessible::Intl() {
+ return static_cast<xpcAccessibleGeneric*>(this)->mIntl.AsAccessible();
+}
+
+inline AccessibleOrProxy xpcAccessible::IntlGeneric() {
+ return static_cast<xpcAccessibleGeneric*>(this)->mIntl;
+}
+
+inline AccessibleOrProxy xpcAccessibleHyperLink::Intl() {
+ return static_cast<xpcAccessibleGeneric*>(this)->mIntl;
+}
+
+inline Accessible* xpcAccessibleSelectable::Intl() {
+ return static_cast<xpcAccessibleGeneric*>(this)->mIntl.AsAccessible();
+}
+
+inline AccessibleOrProxy 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..b3c9ff7e66
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleHyperLink.cpp
@@ -0,0 +1,163 @@
+/* -*- 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 "Accessible-inl.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().IsNull()) return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible()) {
+ *aStartIndex = Intl().AsAccessible()->StartOffset();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ bool isIndexValid = false;
+ uint32_t startOffset = Intl().AsProxy()->StartOffset(&isIndexValid);
+ if (!isIndexValid) return NS_ERROR_FAILURE;
+
+ *aStartIndex = startOffset;
+#endif
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperLink::GetEndIndex(int32_t* aEndIndex) {
+ NS_ENSURE_ARG_POINTER(aEndIndex);
+ *aEndIndex = 0;
+
+ if (Intl().IsNull()) return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible()) {
+ *aEndIndex = Intl().AsAccessible()->EndOffset();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ bool isIndexValid = false;
+ uint32_t endOffset = Intl().AsProxy()->EndOffset(&isIndexValid);
+ if (!isIndexValid) return NS_ERROR_FAILURE;
+
+ *aEndIndex = endOffset;
+#endif
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperLink::GetAnchorCount(int32_t* aAnchorCount) {
+ NS_ENSURE_ARG_POINTER(aAnchorCount);
+ *aAnchorCount = 0;
+
+ if (Intl().IsNull()) return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible()) {
+ *aAnchorCount = Intl().AsAccessible()->AnchorCount();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ bool isCountValid = false;
+ uint32_t anchorCount = Intl().AsProxy()->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().IsNull()) return NS_ERROR_FAILURE;
+
+ if (aIndex < 0) return NS_ERROR_INVALID_ARG;
+
+ if (Intl().IsAccessible()) {
+ if (aIndex >= static_cast<int32_t>(Intl().AsAccessible()->AnchorCount()))
+ return NS_ERROR_INVALID_ARG;
+
+ RefPtr<nsIURI>(Intl().AsAccessible()->AnchorURIAt(aIndex)).forget(aURI);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsCString spec;
+ bool isURIValid = false;
+ Intl().AsProxy()->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().IsNull()) return NS_ERROR_FAILURE;
+
+ if (aIndex < 0) return NS_ERROR_INVALID_ARG;
+
+ if (Intl().IsAccessible()) {
+ if (aIndex >= static_cast<int32_t>(Intl().AsAccessible()->AnchorCount()))
+ return NS_ERROR_INVALID_ARG;
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(Intl().AsAccessible()->AnchorAt(aIndex)));
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ NS_IF_ADDREF(*aAccessible = ToXPC(Intl().AsProxy()->AnchorAt(aIndex)));
+#endif
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperLink::GetValid(bool* aValid) {
+ NS_ENSURE_ARG_POINTER(aValid);
+ *aValid = false;
+
+ if (Intl().IsNull()) return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible()) {
+ *aValid = Intl().AsAccessible()->IsLinkValid();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ *aValid = Intl().AsProxy()->IsLinkValid();
+#endif
+ }
+
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleHyperLink.h b/accessible/xpcom/xpcAccessibleHyperLink.h
new file mode 100644
index 0000000000..27b14ab573
--- /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 "AccessibleOrProxy.h"
+
+class nsIAccessible;
+
+namespace mozilla {
+namespace a11y {
+
+class Accessible;
+
+/**
+ * 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;
+
+ AccessibleOrProxy Intl();
+};
+
+} // namespace a11y
+} // namespace mozilla
+
+#endif
diff --git a/accessible/xpcom/xpcAccessibleHyperText.cpp b/accessible/xpcom/xpcAccessibleHyperText.cpp
new file mode 100644
index 0000000000..45ede2ae25
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleHyperText.cpp
@@ -0,0 +1,744 @@
+/* -*- 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 "Accessible-inl.h"
+#include "HyperTextAccessible-inl.h"
+#include "mozilla/a11y/PDocAccessible.h"
+#include "TextRange.h"
+#include "nsComponentManagerUtils.h"
+#include "xpcAccessibleDocument.h"
+#include "xpcAccessibleTextRange.h"
+
+#include "nsIPersistentProperties2.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.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ *aCharacterCount = Intl()->CharacterCount();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ *aCharacterCount = mIntl.AsProxy()->CharacterCount();
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetText(int32_t aStartOffset, int32_t aEndOffset,
+ nsAString& aText) {
+ aText.Truncate();
+
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->TextSubstring(aStartOffset, aEndOffset, aText);
+ } else {
+ nsString text;
+ mIntl.AsProxy()->TextSubstring(aStartOffset, aEndOffset, text);
+ aText = text;
+ }
+ 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.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->TextBeforeOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset,
+ aText);
+ } else {
+ nsString text;
+ mIntl.AsProxy()->GetTextBeforeOffset(aOffset, aBoundaryType, text,
+ aStartOffset, aEndOffset);
+ aText = text;
+ }
+ 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.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->TextAtOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset,
+ aText);
+ } else {
+ nsString text;
+ mIntl.AsProxy()->GetTextAtOffset(aOffset, aBoundaryType, text, aStartOffset,
+ aEndOffset);
+ aText = text;
+ }
+ 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();
+
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->TextAfterOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset,
+ aText);
+ } else {
+ nsString text;
+ mIntl.AsProxy()->GetTextAfterOffset(aOffset, aBoundaryType, text,
+ aStartOffset, aEndOffset);
+ aText = text;
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetCharacterAtOffset(int32_t aOffset,
+ char16_t* aCharacter) {
+ NS_ENSURE_ARG_POINTER(aCharacter);
+ *aCharacter = L'\0';
+
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ *aCharacter = Intl()->CharAt(aOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ *aCharacter = mIntl.AsProxy()->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.IsNull()) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIPersistentProperties> props;
+ if (mIntl.IsAccessible()) {
+ props = Intl()->TextAttributes(aIncludeDefAttrs, aOffset, aStartOffset,
+ aEndOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ AutoTArray<Attribute, 10> attrs;
+ mIntl.AsProxy()->TextAttributes(aIncludeDefAttrs, aOffset, &attrs,
+ aStartOffset, aEndOffset);
+ uint32_t attrCount = attrs.Length();
+ nsAutoString unused;
+ for (uint32_t i = 0; i < attrCount; i++) {
+ props->SetStringProperty(attrs[i].Name(), attrs[i].Value(), unused);
+ }
+#endif
+ }
+ props.forget(aAttributes);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetDefaultTextAttributes(
+ nsIPersistentProperties** aAttributes) {
+ NS_ENSURE_ARG_POINTER(aAttributes);
+ *aAttributes = nullptr;
+
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIPersistentProperties> props;
+ if (mIntl.IsAccessible()) {
+ props = Intl()->DefaultTextAttributes();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ AutoTArray<Attribute, 10> attrs;
+ mIntl.AsProxy()->DefaultTextAttributes(&attrs);
+ uint32_t attrCount = attrs.Length();
+ nsAutoString unused;
+ for (uint32_t i = 0; i < attrCount; i++) {
+ props->SetStringProperty(attrs[i].Name(), attrs[i].Value(), unused);
+ }
+#endif
+ }
+ 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.IsNull()) return NS_ERROR_FAILURE;
+
+ nsIntRect rect;
+ if (mIntl.IsAccessible()) {
+ rect = Intl()->CharBounds(aOffset, aCoordType);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ rect = mIntl.AsProxy()->CharBounds(aOffset, aCoordType);
+#endif
+ }
+ 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.IsNull()) return NS_ERROR_FAILURE;
+
+ nsIntRect rect;
+ if (mIntl.IsAccessible()) {
+ rect = Intl()->TextBounds(aStartOffset, aEndOffset, aCoordType);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ rect = mIntl.AsProxy()->TextBounds(aStartOffset, aEndOffset, aCoordType);
+#endif
+ }
+ 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.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ *aOffset = Intl()->OffsetAtPoint(aX, aY, aCoordType);
+ } else {
+ *aOffset = mIntl.AsProxy()->OffsetAtPoint(aX, aY, aCoordType);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetCaretOffset(int32_t* aCaretOffset) {
+ NS_ENSURE_ARG_POINTER(aCaretOffset);
+ *aCaretOffset = -1;
+
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ *aCaretOffset = Intl()->CaretOffset();
+ } else {
+ *aCaretOffset = mIntl.AsProxy()->CaretOffset();
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::SetCaretOffset(int32_t aCaretOffset) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->SetCaretOffset(aCaretOffset);
+ } else {
+ mIntl.AsProxy()->SetCaretOffset(aCaretOffset);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetSelectionCount(int32_t* aSelectionCount) {
+ NS_ENSURE_ARG_POINTER(aSelectionCount);
+ *aSelectionCount = 0;
+
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ *aSelectionCount = Intl()->SelectionCount();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ *aSelectionCount = mIntl.AsProxy()->SelectionCount();
+#endif
+ }
+ 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.IsNull()) return NS_ERROR_FAILURE;
+
+ if (aSelectionNum < 0) return NS_ERROR_INVALID_ARG;
+
+ if (mIntl.IsAccessible()) {
+ 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.AsProxy()->SelectionBoundsAt(aSelectionNum, unused, aStartOffset,
+ aEndOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::SetSelectionBounds(int32_t aSelectionNum,
+ int32_t aStartOffset,
+ int32_t aEndOffset) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (aSelectionNum < 0) return NS_ERROR_INVALID_ARG;
+
+ if (mIntl.IsAccessible()) {
+ if (!Intl()->SetSelectionBoundsAt(aSelectionNum, aStartOffset,
+ aEndOffset)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ if (!mIntl.AsProxy()->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.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->AddToSelection(aStartOffset, aEndOffset);
+ } else {
+ mIntl.AsProxy()->AddToSelection(aStartOffset, aEndOffset);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::RemoveSelection(int32_t aSelectionNum) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->RemoveFromSelection(aSelectionNum);
+ } else {
+ mIntl.AsProxy()->RemoveFromSelection(aSelectionNum);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::ScrollSubstringTo(int32_t aStartOffset,
+ int32_t aEndOffset,
+ uint32_t aScrollType) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->ScrollSubstringTo(aStartOffset, aEndOffset, aScrollType);
+ } else {
+ mIntl.AsProxy()->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.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->ScrollSubstringToPoint(aStartOffset, aEndOffset, aCoordinateType,
+ aX, aY);
+ } else {
+ mIntl.AsProxy()->ScrollSubstringToPoint(aStartOffset, aEndOffset,
+ aCoordinateType, aX, aY);
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetEnclosingRange(nsIAccessibleTextRange** aRange) {
+ NS_ENSURE_ARG_POINTER(aRange);
+ *aRange = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ RefPtr<xpcAccessibleTextRange> range = new xpcAccessibleTextRange;
+ Intl()->EnclosingRange(range->mRange);
+ NS_ASSERTION(range->mRange.IsValid(),
+ "Should always have an enclosing range!");
+
+ range.forget(aRange);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetSelectionRanges(nsIArray** aRanges) {
+ NS_ENSURE_ARG_POINTER(aRanges);
+ *aRanges = nullptr;
+
+ if (!Intl()) 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(std::move(ranges[idx])));
+
+ xpcRanges.forget(aRanges);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetVisibleRanges(nsIArray** aRanges) {
+ NS_ENSURE_ARG_POINTER(aRanges);
+ *aRanges = nullptr;
+
+ if (!Intl()) 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;
+ Intl()->VisibleRanges(&ranges);
+ uint32_t len = ranges.Length();
+ for (uint32_t idx = 0; idx < len; idx++)
+ xpcRanges->AppendElement(
+ new xpcAccessibleTextRange(std::move(ranges[idx])));
+
+ xpcRanges.forget(aRanges);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetRangeByChild(nsIAccessible* aChild,
+ nsIAccessibleTextRange** aRange) {
+ NS_ENSURE_ARG_POINTER(aRange);
+ *aRange = nullptr;
+
+ if (!Intl()) return NS_ERROR_FAILURE;
+
+ Accessible* child = aChild->ToInternalAccessible();
+ if (child) {
+ RefPtr<xpcAccessibleTextRange> range = new xpcAccessibleTextRange;
+ Intl()->RangeByChild(child, range->mRange);
+ if (range->mRange.IsValid()) range.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 (!Intl()) return NS_ERROR_FAILURE;
+
+ RefPtr<xpcAccessibleTextRange> range = new xpcAccessibleTextRange;
+ Intl()->RangeAtPoint(aX, aY, range->mRange);
+ if (range->mRange.IsValid()) range.forget(aRange);
+
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleEditableText
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::SetTextContents(const nsAString& aText) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->ReplaceText(aText);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsString text(aText);
+ mIntl.AsProxy()->ReplaceText(text);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::InsertText(const nsAString& aText, int32_t aOffset) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->InsertText(aText, aOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ nsString text(aText);
+ mIntl.AsProxy()->InsertText(text, aOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::CopyText(int32_t aStartOffset, int32_t aEndOffset) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->CopyText(aStartOffset, aEndOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ mIntl.AsProxy()->CopyText(aStartOffset, aEndOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::CutText(int32_t aStartOffset, int32_t aEndOffset) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->CutText(aStartOffset, aEndOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ mIntl.AsProxy()->CutText(aStartOffset, aEndOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::DeleteText(int32_t aStartOffset, int32_t aEndOffset) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ Intl()->DeleteText(aStartOffset, aEndOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ mIntl.AsProxy()->DeleteText(aStartOffset, aEndOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::PasteText(int32_t aOffset) {
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ RefPtr<HyperTextAccessible> acc = Intl();
+ acc->PasteText(aOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ mIntl.AsProxy()->PasteText(aOffset);
+#endif
+ }
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// nsIAccessibleHyperText
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetLinkCount(int32_t* aLinkCount) {
+ NS_ENSURE_ARG_POINTER(aLinkCount);
+ *aLinkCount = 0;
+
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ *aLinkCount = Intl()->LinkCount();
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ *aLinkCount = mIntl.AsProxy()->LinkCount();
+#endif
+ }
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleHyperText::GetLinkAt(int32_t aIndex,
+ nsIAccessibleHyperLink** aLink) {
+ NS_ENSURE_ARG_POINTER(aLink);
+ *aLink = nullptr;
+
+ if (mIntl.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ NS_IF_ADDREF(*aLink = ToXPC(Intl()->LinkAt(aIndex)));
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ NS_IF_ADDREF(*aLink = ToXPC(mIntl.AsProxy()->LinkAt(aIndex)));
+#endif
+ }
+ 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.IsNull()) return NS_ERROR_FAILURE;
+
+ nsCOMPtr<nsIAccessible> xpcLink(do_QueryInterface(aLink));
+ if (Accessible* accLink = xpcLink->ToInternalAccessible()) {
+ *aIndex = Intl()->LinkIndexOf(accLink);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ xpcAccessibleHyperText* linkHyperText =
+ static_cast<xpcAccessibleHyperText*>(xpcLink.get());
+ ProxyAccessible* proxyLink = linkHyperText->mIntl.AsProxy();
+ if (proxyLink) {
+ *aIndex = mIntl.AsProxy()->LinkIndexOf(proxyLink);
+ }
+#endif
+ }
+
+ 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.IsNull()) return NS_ERROR_FAILURE;
+
+ if (mIntl.IsAccessible()) {
+ *aLinkIndex = Intl()->LinkIndexAtOffset(aOffset);
+ } else {
+#if defined(XP_WIN)
+ return NS_ERROR_NOT_IMPLEMENTED;
+#else
+ *aLinkIndex = mIntl.AsProxy()->LinkIndexAtOffset(aOffset);
+#endif
+ }
+ return NS_OK;
+}
diff --git a/accessible/xpcom/xpcAccessibleHyperText.h b/accessible/xpcom/xpcAccessibleHyperText.h
new file mode 100644
index 0000000000..447398c7a3
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleHyperText.h
@@ -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/. */
+
+#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->AsHyperText()->IsTextRole())
+ mSupportedIfaces |= eText;
+ }
+
+ xpcAccessibleHyperText(ProxyAccessible* aProxy, uint32_t aInterfaces)
+ : xpcAccessibleGeneric(aProxy, aInterfaces) {
+ mSupportedIfaces |= eText;
+ }
+
+ NS_DECL_ISUPPORTS_INHERITED
+
+ NS_DECL_NSIACCESSIBLETEXT
+ NS_DECL_NSIACCESSIBLEHYPERTEXT
+ NS_DECL_NSIACCESSIBLEEDITABLETEXT
+
+ protected:
+ virtual ~xpcAccessibleHyperText() {}
+
+ private:
+ HyperTextAccessible* Intl() {
+ if (Accessible* acc = mIntl.AsAccessible()) {
+ 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..3a7fe79474
--- /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 (!Intl()) return NS_ERROR_FAILURE;
+
+ nsIntPoint point = Intl()->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 (!Intl()) return NS_ERROR_FAILURE;
+
+ nsIntSize size = Intl()->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..ad5244b0bf
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleImage.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_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) {}
+
+ xpcAccessibleImage(ProxyAccessible* aProxy, uint32_t aInterfaces)
+ : xpcAccessibleGeneric(aProxy, aInterfaces) {}
+
+ 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:
+ ImageAccessible* Intl() {
+ return mIntl.IsAccessible() ? mIntl.AsAccessible()->AsImage() : nullptr;
+ }
+
+ 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..cb969022e0
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleMacInterface.h
@@ -0,0 +1,108 @@
+/* -*- 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 "nsIAccessibleMacInterface.h"
+
+#include "AccessibleOrProxy.h"
+
+class nsIAccessibleMacInterface;
+
+namespace mozilla {
+namespace a11y {
+
+class xpcAccessibleMacNSObjectWrapper : public nsIAccessibleMacNSObjectWrapper {
+ public:
+ explicit xpcAccessibleMacNSObjectWrapper(id aTextMarker);
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIACCESSIBLEMACNSOBJECTWRAPPER;
+
+ // Get the wrapped NSObject for this interface.
+ id GetNativeObject() const final;
+
+ 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 or proxy.
+ explicit xpcAccessibleMacInterface(AccessibleOrProxy 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..859505aa77
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleMacInterface.mm
@@ -0,0 +1,509 @@
+/* -*- 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 "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"
+
+#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() const { return mNativeObject; }
+
+// xpcAccessibleMacInterface
+
+NS_IMPL_ISUPPORTS_INHERITED(xpcAccessibleMacInterface, xpcAccessibleMacNSObjectWrapper,
+ nsIAccessibleMacInterface)
+
+xpcAccessibleMacInterface::xpcAccessibleMacInterface(AccessibleOrProxy aObj)
+ : xpcAccessibleMacNSObjectWrapper(GetNativeFromGeckoAccessible(aObj)) {}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::GetAttributeNames(nsTArray<nsString>& aAttributeNames) {
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT
+
+ 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_ABORT_BLOCK_NSRESULT
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::GetParameterizedAttributeNames(nsTArray<nsString>& aAttributeNames) {
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT
+
+ 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_ABORT_BLOCK_NSRESULT
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::GetActionNames(nsTArray<nsString>& aActionNames) {
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT
+
+ 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_ABORT_BLOCK_NSRESULT
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::PerformAction(const nsAString& aActionName) {
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT
+
+ if (!mNativeObject || [mNativeObject isExpired]) {
+ return NS_ERROR_NOT_AVAILABLE;
+ }
+
+ NSString* actionName = nsCocoaUtils::ToNSString(aActionName);
+ [mNativeObject accessibilityPerformAction:actionName];
+
+ return NS_OK;
+
+ NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT
+}
+
+NS_IMETHODIMP
+xpcAccessibleMacInterface::GetAttributeValue(const nsAString& aAttributeName, JSContext* aCx,
+ JS::MutableHandleValue aResult) {
+ NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT
+
+ 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_ABORT_BLOCK_NSRESULT
+}
+
+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);
+
+ return NS_OK;
+}
+
+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 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..9e24391f95
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleSelectable.cpp
@@ -0,0 +1,120 @@
+/* -*- 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-inl.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..97e5941dfa
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTable.cpp
@@ -0,0 +1,395 @@
+/* -*- 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 "Accessible.h"
+#include "TableAccessible.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..2875b39f92
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTable.h
@@ -0,0 +1,82 @@
+/* -*- 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 {
+
+/**
+ * XPCOM wrapper around TableAccessible class.
+ */
+class xpcAccessibleTable : public xpcAccessibleHyperText,
+ public nsIAccessibleTable {
+ public:
+ explicit xpcAccessibleTable(Accessible* aIntl)
+ : xpcAccessibleHyperText(aIntl) {}
+
+ xpcAccessibleTable(ProxyAccessible* aProxy, uint32_t aInterfaces)
+ : xpcAccessibleHyperText(aProxy, aInterfaces) {}
+
+ 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:
+ TableAccessible* Intl() {
+ return mIntl.IsAccessible() ? mIntl.AsAccessible()->AsTable() : nullptr;
+ }
+
+ 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..9deb2a4213
--- /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 "Accessible.h"
+#include "nsIAccessibleTable.h"
+#include "TableAccessible.h"
+#include "TableCellAccessible.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;
+
+ TableAccessible* 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..abfc68ca9e
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTableCell.h
@@ -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/. */
+
+#ifndef mozilla_a11y_xpcom_xpcAccessibletableCell_h_
+#define mozilla_a11y_xpcom_xpcAccessibletableCell_h_
+
+#include "nsIAccessibleTable.h"
+
+#include "xpcAccessibleHyperText.h"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * XPCOM wrapper around TableAccessibleCell class.
+ */
+class xpcAccessibleTableCell : public xpcAccessibleHyperText,
+ public nsIAccessibleTableCell {
+ public:
+ explicit xpcAccessibleTableCell(Accessible* aIntl)
+ : xpcAccessibleHyperText(aIntl) {}
+
+ xpcAccessibleTableCell(ProxyAccessible* aProxy, uint32_t aInterfaces)
+ : xpcAccessibleHyperText(aProxy, aInterfaces) {}
+
+ 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:
+ TableCellAccessible* Intl() {
+ if (Accessible* acc = mIntl.AsAccessible()) {
+ return acc->AsTableCell();
+ }
+
+ return nullptr;
+ }
+
+ 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..0ffcc6bd0b
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTextRange.cpp
@@ -0,0 +1,182 @@
+/* -*- 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_IMPL_CYCLE_COLLECTION(xpcAccessibleTextRange, mRange.mRoot,
+ mRange.mStartContainer, mRange.mEndContainer)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(xpcAccessibleTextRange)
+ NS_INTERFACE_MAP_ENTRY(nsIAccessibleTextRange)
+ NS_INTERFACE_MAP_ENTRY(xpcAccessibleTextRange)
+ NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIAccessibleTextRange)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(xpcAccessibleTextRange)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(xpcAccessibleTextRange)
+
+// nsIAccessibleTextRange
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetStartContainer(nsIAccessibleText** aAnchor) {
+ NS_ENSURE_ARG_POINTER(aAnchor);
+ NS_IF_ADDREF(*aAnchor = ToXPCText(mRange.StartContainer()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetStartOffset(int32_t* aOffset) {
+ NS_ENSURE_ARG_POINTER(aOffset);
+ *aOffset = mRange.StartOffset();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetEndContainer(nsIAccessibleText** aAnchor) {
+ NS_ENSURE_ARG_POINTER(aAnchor);
+ NS_IF_ADDREF(*aAnchor = ToXPCText(mRange.EndContainer()));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetEndOffset(int32_t* aOffset) {
+ NS_ENSURE_ARG_POINTER(aOffset);
+ *aOffset = mRange.EndOffset();
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetContainer(nsIAccessible** aContainer) {
+ NS_ENSURE_ARG_POINTER(aContainer);
+ NS_IF_ADDREF(*aContainer = ToXPC(mRange.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;
+ mRange.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 = (mRange == xpcRange->mRange);
+ 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;
+
+ TextPoint p =
+ (aEndPoint == EndPoint_Start) ? mRange.StartPoint() : mRange.EndPoint();
+ TextPoint otherPoint = (aOtherRangeEndPoint == EndPoint_Start)
+ ? xpcRange->mRange.StartPoint()
+ : xpcRange->mRange.EndPoint();
+
+ if (p == otherPoint)
+ *aResult = 0;
+ else
+ *aResult = p < otherPoint ? -1 : 1;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetText(nsAString& aText) {
+ nsAutoString text;
+ mRange.Text(text);
+ aText.Assign(text);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::GetBounds(nsIArray** aRectList) { return NS_OK; }
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::Move(uint32_t aUnit, int32_t aCount) { return NS_OK; }
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::MoveStart(uint32_t aUnit, int32_t aCount) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::MoveEnd(uint32_t aUnit, int32_t aCount) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::Normalize(uint32_t aUnit) { return NS_OK; }
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::Crop(nsIAccessible* aContainer, bool* aSuccess) {
+ Accessible* container = aContainer->ToInternalAccessible();
+ NS_ENSURE_TRUE(container, NS_ERROR_INVALID_ARG);
+
+ *aSuccess = mRange.Crop(container);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::FindText(const nsAString& aText, bool aIsBackward,
+ bool aIsIgnoreCase,
+ nsIAccessibleTextRange** aRange) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::FindAttr(uint32_t aAttr, nsIVariant* aVal,
+ bool aIsBackward,
+ nsIAccessibleTextRange** aRange) {
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::AddToSelection() { return NS_OK; }
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::RemoveFromSelection() { return NS_OK; }
+
+NS_IMETHODIMP
+xpcAccessibleTextRange::Select() { 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..0f73934b6b
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleTextRange.h
@@ -0,0 +1,85 @@
+/* -*- 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 "nsCycleCollectionParticipant.h"
+#include "nsIAccessibleTextRange.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)
+ : mRange(std::forward<TextRange>(aRange)) {}
+
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_CLASS(xpcAccessibleTextRange)
+
+ 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 GetBounds(nsIArray** aRectList) final;
+ NS_IMETHOD Move(uint32_t aUnit, int32_t aCount) final;
+ NS_IMETHOD MoveStart(uint32_t aUnit, int32_t aCount) final;
+ NS_IMETHOD MoveEnd(uint32_t aUnit, int32_t aCount) final;
+ NS_IMETHOD Normalize(uint32_t aUnit) final;
+ NS_IMETHOD Crop(nsIAccessible* aContainer, bool* aSuccess) final;
+ NS_IMETHOD FindText(const nsAString& aText, bool aIsBackward,
+ bool aIsIgnoreCase,
+ nsIAccessibleTextRange** aRange) final;
+ NS_IMETHOD FindAttr(uint32_t aAttr, nsIVariant* aVal, bool aIsBackward,
+ nsIAccessibleTextRange** aRange) final;
+ NS_IMETHOD AddToSelection() final;
+ NS_IMETHOD RemoveFromSelection() final;
+ NS_IMETHOD Select() final;
+ NS_IMETHOD ScrollIntoView(uint32_t aHow) final;
+
+ NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLETEXTRANGE_IMPL_IID)
+
+ private:
+ xpcAccessibleTextRange() {}
+
+ ~xpcAccessibleTextRange() {}
+
+ friend class xpcAccessibleHyperText;
+
+ xpcAccessibleTextRange(const xpcAccessibleTextRange&) = delete;
+ xpcAccessibleTextRange& operator=(const xpcAccessibleTextRange&) = delete;
+
+ TextRange mRange;
+};
+
+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..93ed32e2b3
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibleValue.cpp
@@ -0,0 +1,115 @@
+/* -*- 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 "Accessible.h"
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetMaximumValue(double* aValue) {
+ NS_ENSURE_ARG_POINTER(aValue);
+ *aValue = 0;
+
+ if (Intl().IsNull()) return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ double value;
+ if (Intl().IsAccessible()) {
+ value = Intl().AsAccessible()->MaxValue();
+ } else {
+ value = Intl().AsProxy()->MaxValue();
+ }
+
+ if (!IsNaN(value)) *aValue = value;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetMinimumValue(double* aValue) {
+ NS_ENSURE_ARG_POINTER(aValue);
+ *aValue = 0;
+
+ if (Intl().IsNull()) return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ double value;
+ if (Intl().IsAccessible()) {
+ value = Intl().AsAccessible()->MinValue();
+ } else {
+ value = Intl().AsProxy()->MinValue();
+ }
+
+ if (!IsNaN(value)) *aValue = value;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetCurrentValue(double* aValue) {
+ NS_ENSURE_ARG_POINTER(aValue);
+ *aValue = 0;
+
+ if (Intl().IsNull()) return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ double value;
+ if (Intl().IsAccessible()) {
+ value = Intl().AsAccessible()->CurValue();
+ } else {
+ value = Intl().AsProxy()->CurValue();
+ }
+
+ if (!IsNaN(value)) *aValue = value;
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::SetCurrentValue(double aValue) {
+ if (Intl().IsNull()) return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible()) {
+ Intl().AsAccessible()->SetCurValue(aValue);
+ } else {
+ Intl().AsProxy()->SetCurValue(aValue);
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibleValue::GetMinimumIncrement(double* aValue) {
+ NS_ENSURE_ARG_POINTER(aValue);
+ *aValue = 0;
+
+ if (Intl().IsNull()) return NS_ERROR_FAILURE;
+
+ if (Intl().IsAccessible() && Intl().AsAccessible()->IsDefunct())
+ return NS_ERROR_FAILURE;
+
+ double value;
+ if (Intl().IsAccessible()) {
+ value = Intl().AsAccessible()->Step();
+ } else {
+ value = Intl().AsProxy()->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..74586cd72b
--- /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 Accessible;
+
+/**
+ * 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:
+ AccessibleOrProxy Intl();
+
+ xpcAccessibleValue(const xpcAccessibleValue&) = delete;
+ xpcAccessibleValue& operator=(const xpcAccessibleValue&) = delete;
+};
+
+} // namespace a11y
+} // namespace mozilla
+#endif