diff options
Diffstat (limited to 'accessible/xpcom')
31 files changed, 5066 insertions, 0 deletions
diff --git a/accessible/xpcom/AccEventGen.py b/accessible/xpcom/AccEventGen.py new file mode 100755 index 0000000000..6af54c34db --- /dev/null +++ b/accessible/xpcom/AccEventGen.py @@ -0,0 +1,228 @@ +#!/usr/bin/env python +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import sys +import os + +import buildconfig +import mozpack.path as mozpath + +# The xpidl parser is not incorporated in the in-tree virtualenv. +xpidl_dir = mozpath.join(buildconfig.topsrcdir, 'xpcom', 'idl-parser', + 'xpidl') +xpidl_cachedir = mozpath.join(buildconfig.topobjdir, 'xpcom', 'idl-parser', + 'xpidl') +sys.path.extend([xpidl_dir, xpidl_cachedir]) +import xpidl + +# 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) + return idl, idlFile + +class Configuration: + def __init__(self, filename): + config = {} + execfile(filename, 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 not e 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(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, xpidllex, xpidlyacc): + deps = set() + conf, inc_dir = get_conf(conf_file) + deps.update(print_header_file(fd, conf, inc_dir)) + with open('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..0824bb78a0 --- /dev/null +++ b/accessible/xpcom/AccEvents.conf @@ -0,0 +1,18 @@ +""" -*- 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', + 'HideEvent', + 'CaretMoveEvent', + 'ObjectAttributeChangedEvent', + 'TableChangeEvent', + 'VirtualCursorChangeEvent' + ] diff --git a/accessible/xpcom/moz.build b/accessible/xpcom/moz.build new file mode 100644 index 0000000000..ec54a197a4 --- /dev/null +++ b/accessible/xpcom/moz.build @@ -0,0 +1,66 @@ +# -*- 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 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']: + LOCAL_INCLUDES += [ + '/accessible/atk', + ] +elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': + LOCAL_INCLUDES += [ + '/accessible/windows/msaa', + ] +elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa': + LOCAL_INCLUDES += [ + '/accessible/mac', + ] +else: + LOCAL_INCLUDES += [ + '/accessible/other', + ] + +GENERATED_FILES += [('xpcAccEvents.h', 'xpcAccEvents.cpp')] + +xpc_acc = GENERATED_FILES[('xpcAccEvents.h', 'xpcAccEvents.cpp')] +xpc_acc.script = 'AccEventGen.py:gen_files' +xpc_acc.inputs += ['AccEvents.conf', '!/xpcom/idl-parser/xpidl/xpidllex.py', '!/xpcom/idl-parser/xpidl/xpidlyacc.py'] + +FINAL_LIBRARY = 'xul' + +include('/ipc/chromium/chromium-config.mozbuild') + +if CONFIG['GNU_CXX']: + CXXFLAGS += ['-Wno-error=shadow'] diff --git a/accessible/xpcom/nsAccessibleRelation.cpp b/accessible/xpcom/nsAccessibleRelation.cpp new file mode 100644 index 0000000000..c22cb22020 --- /dev/null +++ b/accessible/xpcom/nsAccessibleRelation.cpp @@ -0,0 +1,79 @@ +/* -*- 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)), false); +} + +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))), + false); + } +} + +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..1f201d6cca --- /dev/null +++ b/accessible/xpcom/nsAccessibleRelation.h @@ -0,0 +1,50 @@ +/* -*- 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..97c0d0e721 --- /dev/null +++ b/accessible/xpcom/xpcAccessibilityService.cpp @@ -0,0 +1,246 @@ +/* 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" + +#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 (!mRefCnt.isThreadSafe) + NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService); + nsrefcnt count = ++mRefCnt; + NS_LOG_ADDREF(this, count, "xpcAccessibilityService", sizeof(*this)); + + if (mRefCnt > 1) { + GetOrCreateAccService(nsAccessibilityService::eXPCOM); + } + + return count; +} + +NS_IMETHODIMP_(MozExternalRefCountType) +xpcAccessibilityService::Release(void) +{ + MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); + + if (!mRefCnt.isThreadSafe) { + NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService); + } + + nsrefcnt count = --mRefCnt; + NS_LOG_RELEASE(this, count, "xpcAccessibilityService"); + + if (count == 0) { + if (!mRefCnt.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) { + mShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID); + if (mShutdownTimer) { + mShutdownTimer->InitWithFuncCallback(ShutdownCallback, this, 100, + nsITimer::TYPE_ONE_SHOT); + } + } + + return count; +} + +NS_IMPL_QUERY_INTERFACE(xpcAccessibilityService, nsIAccessibilityService, + nsIAccessibleRetrieval) + +NS_IMETHODIMP +xpcAccessibilityService::GetApplicationAccessible(nsIAccessible** aAccessibleApplication) +{ + NS_ENSURE_ARG_POINTER(aAccessibleApplication); + + NS_IF_ADDREF(*aAccessibleApplication = XPCApplicationAcc()); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode, + nsIAccessible **aAccessible) +{ + NS_ENSURE_ARG_POINTER(aAccessible); + *aAccessible = nullptr; + if (!aNode) { + return NS_OK; + } + + nsCOMPtr<nsINode> node(do_QueryInterface(aNode)); + if (!node) { + return NS_ERROR_INVALID_ARG; + } + + DocAccessible* document = GetAccService()->GetDocAccessible(node->OwnerDoc()); + if (document) { + NS_IF_ADDREF(*aAccessible = ToXPC(document->GetAccessible(node))); + } + + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString) +{ + GetAccService()->GetStringRole(aRole, aString); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState, + nsISupports **aStringStates) +{ + GetAccService()->GetStringStates(aState, aExtraState, aStringStates); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibilityService::GetStringEventType(uint32_t aEventType, + nsAString& aString) +{ + GetAccService()->GetStringEventType(aEventType, aString); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibilityService::GetStringRelationType(uint32_t aRelationType, + nsAString& aString) +{ + GetAccService()->GetStringRelationType(aRelationType, aString); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode, + nsIAccessible** aAccessible) +{ + NS_ENSURE_ARG_POINTER(aAccessible); + *aAccessible = nullptr; + if (!aNode) { + return NS_OK; + } + + nsCOMPtr<nsINode> node(do_QueryInterface(aNode)); + if (!node) { + return NS_ERROR_INVALID_ARG; + } + + // 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 = GetAccService()->FindAccessibleInCache(node); + if (!accessible) { + nsCOMPtr<nsIDocument> document(do_QueryInterface(node)); + if (document) { + accessible = mozilla::a11y::GetExistingDocAccessible(document); + } + } + + 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_GetAccessibilityService +//////////////////////////////////////////////////////////////////////////////// + +nsresult +NS_GetAccessibilityService(nsIAccessibilityService** aResult) +{ + NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER); + *aResult = nullptr; + + GetOrCreateAccService(nsAccessibilityService::eXPCOM); + + 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..76389a8a5d --- /dev/null +++ b/accessible/xpcom/xpcAccessibilityService.h @@ -0,0 +1,66 @@ +/* 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" + +class xpcAccessibilityService : public nsIAccessibleRetrieval +{ + +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIACCESSIBILITYSERVICE + NS_DECL_NSIACCESSIBLERETRIEVAL + + /** + * 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() { }; + + 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..843b21cd2c --- /dev/null +++ b/accessible/xpcom/xpcAccessible.cpp @@ -0,0 +1,826 @@ +/* -*- 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 "nsIAccessibleRelation.h" +#include "nsIAccessibleRole.h" +#include "nsAccessibleRelation.h" +#include "Relation.h" +#include "Role.h" +#include "RootAccessible.h" +#include "xpcAccessibleDocument.h" + +#include "nsIMutableArray.h" +#include "nsIPersistentProperties2.h" + +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)), false); + } + + 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::GetDOMNode(nsIDOMNode** aDOMNode) +{ + NS_ENSURE_ARG_POINTER(aDOMNode); + *aDOMNode = nullptr; + + if (!Intl()) + return NS_ERROR_FAILURE; + + nsINode* node = Intl()->GetNode(); + if (node) + CallQueryInterface(node, aDOMNode); + + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessible::GetId(nsAString& aID) +{ +#if defined(XP_WIN) + return NS_ERROR_NOT_IMPLEMENTED; +#else + ProxyAccessible* proxy = IntlGeneric().AsProxy(); + if (!proxy) { + return NS_ERROR_FAILURE; + } + + nsString id; + proxy->DOMNodeID(id); + aID.Assign(id); + + return NS_OK; +#endif +} + +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); + + nsCOMPtr<nsIPersistentProperties> props = + do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID); + 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::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(); + } + + *aX = rect.x; + *aY = rect.y; + *aWidth = rect.width; + *aHeight = rect.height; + + 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; + + if (!Intl()) + return NS_ERROR_FAILURE; + + GroupPos groupPos = Intl()->GroupPosition(); + + *aGroupLevel = groupPos.level; + *aSimilarItemsInGroup = groupPos.setSize; + *aPositionInGroup = groupPos.posInSet; + + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessible::GetRelationByType(uint32_t aType, + nsIAccessibleRelation** aRelation) +{ + NS_ENSURE_ARG_POINTER(aRelation); + *aRelation = nullptr; + + NS_ENSURE_ARG(aType <= static_cast<uint32_t>(RelationType::LAST)); + + if (IntlGeneric().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; + } + +#if defined(XP_WIN) + return NS_ERROR_NOT_IMPLEMENTED; +#else + ProxyAccessible* proxy = IntlGeneric().AsProxy(); + nsTArray<ProxyAccessible*> targets = + proxy->RelationByType(static_cast<RelationType>(aType)); + NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &targets)); + + return NS_OK; +#endif +} + +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, false); + } + } + + 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; + + if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) { +#if defined(XP_WIN) + return NS_ERROR_NOT_IMPLEMENTED; +#else + NS_IF_ADDREF(*aAccessible = + ToXPC(proxy->ChildAtPoint(aX, aY, Accessible::eDirectChild))); +#endif + } else { + NS_IF_ADDREF(*aAccessible = + ToXPC(Intl()->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; + + if (ProxyAccessible* proxy = IntlGeneric().AsProxy()) { +#if defined(XP_WIN) + return NS_ERROR_NOT_IMPLEMENTED; +#else + NS_IF_ADDREF(*aAccessible = + ToXPC(proxy->ChildAtPoint(aX, aY, Accessible::eDeepestChild))); +#endif + } else { + 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()) { +#if defined(XP_WIN) + return NS_ERROR_NOT_IMPLEMENTED; +#else + proxy->TakeFocus(); +#endif + } 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 { + 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; +} diff --git a/accessible/xpcom/xpcAccessible.h b/accessible/xpcom/xpcAccessible.h new file mode 100644 index 0000000000..cecc727203 --- /dev/null +++ b/accessible/xpcom/xpcAccessible.h @@ -0,0 +1,106 @@ +/* -*- 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 override; + NS_IMETHOD GetNextSibling(nsIAccessible** aNextSibling) final override; + NS_IMETHOD GetPreviousSibling(nsIAccessible** aPreviousSibling) + final override; + NS_IMETHOD GetFirstChild(nsIAccessible** aFirstChild) final override; + NS_IMETHOD GetLastChild(nsIAccessible** aLastChild) final override; + NS_IMETHOD GetChildCount(int32_t* aChildCount) final override; + NS_IMETHOD GetChildAt(int32_t aChildIndex, nsIAccessible** aChild) + final override; + NS_IMETHOD GetChildren(nsIArray** aChildren) final override; + NS_IMETHOD GetIndexInParent(int32_t* aIndexInParent) final override; + + NS_IMETHOD GetDOMNode(nsIDOMNode** aDOMNode) final override; + NS_IMETHOD GetId(nsAString& aID) final override; + NS_IMETHOD GetDocument(nsIAccessibleDocument** aDocument) final override; + NS_IMETHOD GetRootDocument(nsIAccessibleDocument** aRootDocument) + final override; + + NS_IMETHOD GetRole(uint32_t* aRole) final override; + NS_IMETHOD GetState(uint32_t* aState, uint32_t* aExtraState) + final override; + + NS_IMETHOD GetDescription(nsAString& aDescription) final override; + NS_IMETHOD GetName(nsAString& aName) final override; + NS_IMETHOD GetLanguage(nsAString& aLanguage) final override; + NS_IMETHOD GetValue(nsAString& aValue) final override; + NS_IMETHOD GetHelp(nsAString& aHelp) final override; + + NS_IMETHOD GetAccessKey(nsAString& aAccessKey) final override; + NS_IMETHOD GetKeyboardShortcut(nsAString& aKeyBinding) final override; + + NS_IMETHOD GetAttributes(nsIPersistentProperties** aAttributes) + final override; + NS_IMETHOD GetBounds(int32_t* aX, int32_t* aY, + int32_t* aWidth, int32_t* aHeight) final override; + NS_IMETHOD GroupPosition(int32_t* aGroupLevel, int32_t* aSimilarItemsInGroup, + int32_t* aPositionInGroup) final override; + NS_IMETHOD GetRelationByType(uint32_t aType, + nsIAccessibleRelation** aRelation) + final override; + NS_IMETHOD GetRelations(nsIArray** aRelations) final override; + + NS_IMETHOD GetFocusedChild(nsIAccessible** aChild) final override; + NS_IMETHOD GetChildAtPoint(int32_t aX, int32_t aY, + nsIAccessible** aAccessible) final override; + NS_IMETHOD GetDeepestChildAtPoint(int32_t aX, int32_t aY, + nsIAccessible** aAccessible) + final override; + + NS_IMETHOD SetSelected(bool aSelect) final override; + NS_IMETHOD TakeSelection() final override; + NS_IMETHOD TakeFocus() final override; + + NS_IMETHOD GetActionCount(uint8_t* aActionCount) final override; + NS_IMETHOD GetActionName(uint8_t aIndex, nsAString& aName) final override; + NS_IMETHOD GetActionDescription(uint8_t aIndex, nsAString& aDescription) + final override; + NS_IMETHOD DoAction(uint8_t aIndex) final override; + + NS_IMETHOD ScrollTo(uint32_t aHow) final override; + NS_IMETHOD ScrollToPoint(uint32_t aCoordinateType, + int32_t aX, int32_t aY) final override; + +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..af2bde466f --- /dev/null +++ b/accessible/xpcom/xpcAccessibleApplication.cpp @@ -0,0 +1,69 @@ +/* -*- 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..24edbcbdbc --- /dev/null +++ b/accessible/xpcom/xpcAccessibleApplication.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_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 override; + NS_IMETHOD GetAppVersion(nsAString& aVersion) final override; + NS_IMETHOD GetPlatformName(nsAString& aName) final override; + NS_IMETHOD GetPlatformVersion(nsAString& aVersion) final override; + +protected: + virtual ~xpcAccessibleApplication() {} + +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..055cb8a860 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleDocument.cpp @@ -0,0 +1,262 @@ +/* -*- 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" +#include "nsIDOMDocument.h" + +using namespace mozilla; +using namespace mozilla::a11y; + +//////////////////////////////////////////////////////////////////////////////// +// nsISupports and cycle collection + +NS_IMPL_CYCLE_COLLECTION_CLASS(xpcAccessibleDocument) + +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(xpcAccessibleDocument, + xpcAccessibleGeneric) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCache) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END + +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(xpcAccessibleDocument, + xpcAccessibleGeneric) + tmp->mCache.Clear(); +NS_IMPL_CYCLE_COLLECTION_UNLINK_END + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(xpcAccessibleDocument) + NS_INTERFACE_MAP_ENTRY(nsIAccessibleDocument) +NS_INTERFACE_MAP_END_INHERITING(xpcAccessibleHyperText) + +NS_IMPL_ADDREF_INHERITED(xpcAccessibleDocument, xpcAccessibleHyperText) +NS_IMPL_RELEASE_INHERITED(xpcAccessibleDocument, xpcAccessibleHyperText) + +//////////////////////////////////////////////////////////////////////////////// +// 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(nsIDOMDocument** aDOMDocument) +{ + NS_ENSURE_ARG_POINTER(aDOMDocument); + *aDOMDocument = nullptr; + + if (!Intl()) + return NS_ERROR_FAILURE; + + if (Intl()->DocumentNode()) + CallQueryInterface(Intl()->DocumentNode(), aDOMDocument); + + 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.GetWeak(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.GetWeak(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..651fe22552 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleDocument.h @@ -0,0 +1,150 @@ +/* -*- 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 + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(xpcAccessibleDocument, + xpcAccessibleGeneric) + + // nsIAccessibleDocument + NS_IMETHOD GetURL(nsAString& aURL) final override; + NS_IMETHOD GetTitle(nsAString& aTitle) final override; + NS_IMETHOD GetMimeType(nsAString& aType) final override; + NS_IMETHOD GetDocType(nsAString& aType) final override; + NS_IMETHOD GetDOMDocument(nsIDOMDocument** aDOMDocument) final override; + NS_IMETHOD GetWindow(mozIDOMWindowProxy** aDOMWindow) final override; + NS_IMETHOD GetParentDocument(nsIAccessibleDocument** aDocument) + final override; + NS_IMETHOD GetChildDocumentCount(uint32_t* aCount) final override; + NS_IMETHOD GetChildDocumentAt(uint32_t aIndex, + nsIAccessibleDocument** aDocument) + final override; + NS_IMETHOD GetVirtualCursor(nsIAccessiblePivot** aVirtualCursor) + final override; + + /** + * 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.GetWeak(aAccessible); + if (xpcAcc) + xpcAcc->Shutdown(); + + mCache.Remove(aAccessible); + } + + void NotifyOfShutdown(ProxyAccessible* aProxy) + { + MOZ_ASSERT(mRemote); + xpcAccessibleGeneric* acc = mCache.GetWeak(aProxy); + if (acc) { + acc->Shutdown(); + } + + mCache.Remove(aProxy); + } + + friend class DocManager; + friend class DocAccessible; + friend class ProxyAccessible; + friend class ProxyAccessibleBase<ProxyAccessible>; + + xpcAccessibleDocument(const xpcAccessibleDocument&) = delete; + xpcAccessibleDocument& operator =(const xpcAccessibleDocument&) = delete; + + nsRefPtrHashtable<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..5793b8a2ef --- /dev/null +++ b/accessible/xpcom/xpcAccessibleGeneric.cpp @@ -0,0 +1,46 @@ +/* -*- 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" + +using namespace mozilla::a11y; + +//////////////////////////////////////////////////////////////////////////////// +// nsISupports and cycle collection + +NS_IMPL_CYCLE_COLLECTION_0(xpcAccessibleGeneric) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(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_CYCLE_COLLECTING_ADDREF(xpcAccessibleGeneric) +NS_IMPL_CYCLE_COLLECTING_RELEASE(xpcAccessibleGeneric) + +//////////////////////////////////////////////////////////////////////////////// +// 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..da51d27285 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleGeneric.h @@ -0,0 +1,110 @@ +/* -*- 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_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(xpcAccessibleGeneric, nsIAccessible) + + // nsIAccessible + virtual Accessible* ToInternalAccessible() const final override; + + // 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..644f355f07 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleHyperLink.cpp @@ -0,0 +1,180 @@ +/* -*- 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 "xpcAccessibleDocument.h" +#include "nsNetUtil.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..0f986cfd47 --- /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" + +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 override; + NS_IMETHOD GetStartIndex(int32_t* aStartIndex) final override; + NS_IMETHOD GetEndIndex(int32_t* aEndIndex) final override; + NS_IMETHOD GetURI(int32_t aIndex, nsIURI** aURI) final override; + NS_IMETHOD GetAnchor(int32_t aIndex, nsIAccessible** aAccessible) + final override; + NS_IMETHOD GetValid(bool* aValid) final override; + +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..b31544ac7f --- /dev/null +++ b/accessible/xpcom/xpcAccessibleHyperText.cpp @@ -0,0 +1,822 @@ +/* -*- 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 "TextRange.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 + } + *aX = rect.x; *aY = rect.y; + *aWidth = rect.width; *aHeight = rect.height; + 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 + } + *aX = rect.x; *aY = rect.y; + *aWidth = rect.width; *aHeight = rect.height; + 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 { +#if defined(XP_WIN) + return NS_ERROR_NOT_IMPLEMENTED; +#else + *aOffset = mIntl.AsProxy()->OffsetAtPoint(aX, aY, aCoordType); +#endif + } + 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(Move(ranges[idx])), + false); + + 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(Move(ranges[idx])), + false); + + 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()) { + Intl()->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..fbdac95cf8 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleHyperText.h @@ -0,0 +1,62 @@ +/* -*- 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..c0ef317215 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleImage.cpp @@ -0,0 +1,55 @@ +/* -*- 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..1c0bc805fd --- /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 override; + NS_IMETHOD GetImageSize(int32_t* aWidth, int32_t* aHeight) final override; + +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/xpcAccessibleSelectable.cpp b/accessible/xpcom/xpcAccessibleSelectable.cpp new file mode 100644 index 0000000000..df63e116c8 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleSelectable.cpp @@ -0,0 +1,134 @@ +/* -*- 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 "xpcAccessibleDocument.h" + +#include "nsIMutableArray.h" + +using namespace mozilla::a11y; + +NS_IMETHODIMP +xpcAccessibleSelectable::GetSelectedItems(nsIArray** aSelectedItems) +{ + NS_ENSURE_ARG_POINTER(aSelectedItems); + *aSelectedItems = nullptr; + + if (!Intl()) + return NS_ERROR_FAILURE; + NS_PRECONDITION(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])), false); + + 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; + NS_PRECONDITION(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; + NS_PRECONDITION(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; + NS_PRECONDITION(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; + NS_PRECONDITION(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; + NS_PRECONDITION(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; + NS_PRECONDITION(Intl()->IsSelect(), "Called on non selectable widget!"); + + *aIsMultiSelect = Intl()->SelectAll(); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleSelectable::UnselectAll() +{ + if (!Intl()) + return NS_ERROR_FAILURE; + NS_PRECONDITION(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..7b2f8a8276 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleSelectable.h @@ -0,0 +1,54 @@ +/* -*- 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 override; + NS_IMETHOD GetSelectedItemCount(uint32_t* aSelectedItemCount) + final override; + NS_IMETHOD GetSelectedItemAt(uint32_t aIndex, nsIAccessible** aItem) + final override; + NS_IMETHOD IsItemSelected(uint32_t aIndex, bool* aIsSelected) + final override; + NS_IMETHOD AddItemToSelection(uint32_t aIndex) final override; + NS_IMETHOD RemoveItemFromSelection(uint32_t aIndex) final override; + NS_IMETHOD SelectAll(bool* aIsMultiSelect) final override; + NS_IMETHOD UnselectAll() final override; + +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..0787bf73fd --- /dev/null +++ b/accessible/xpcom/xpcAccessibleTable.cpp @@ -0,0 +1,493 @@ +/* -*- 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 "xpcAccessibleDocument.h" + +#include "nsIMutableArray.h" +#include "nsComponentManagerUtils.h" + +using namespace mozilla::a11y; + +static const uint32_t XPC_TABLE_DEFAULT_SIZE = 40; + +//////////////////////////////////////////////////////////////////////////////// +// nsISupports + +NS_IMPL_ISUPPORTS_INHERITED(xpcAccessibleTable, + xpcAccessibleGeneric, + 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)), false); + } + + NS_ADDREF(*aSelectedCells = selCells); + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleTable::GetSelectedCellIndices(uint32_t* aCellsArraySize, + int32_t** aCellsArray) +{ + NS_ENSURE_ARG_POINTER(aCellsArraySize); + *aCellsArraySize = 0; + + NS_ENSURE_ARG_POINTER(aCellsArray); + *aCellsArray = 0; + + if (!Intl()) + return NS_ERROR_FAILURE; + + AutoTArray<uint32_t, XPC_TABLE_DEFAULT_SIZE> cellsArray; + Intl()->SelectedCellIndices(&cellsArray); + + *aCellsArraySize = cellsArray.Length(); + *aCellsArray = static_cast<int32_t*> + (moz_xmalloc(*aCellsArraySize * sizeof(int32_t))); + memcpy(*aCellsArray, cellsArray.Elements(), + *aCellsArraySize * sizeof(int32_t)); + + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleTable::GetSelectedColumnIndices(uint32_t* aColsArraySize, + int32_t** aColsArray) +{ + NS_ENSURE_ARG_POINTER(aColsArraySize); + *aColsArraySize = 0; + + NS_ENSURE_ARG_POINTER(aColsArray); + *aColsArray = 0; + + if (!Intl()) + return NS_ERROR_FAILURE; + + AutoTArray<uint32_t, XPC_TABLE_DEFAULT_SIZE> colsArray; + Intl()->SelectedColIndices(&colsArray); + + *aColsArraySize = colsArray.Length(); + *aColsArray = static_cast<int32_t*> + (moz_xmalloc(*aColsArraySize * sizeof(int32_t))); + memcpy(*aColsArray, colsArray.Elements(), + *aColsArraySize * sizeof(int32_t)); + + return NS_OK; +} + +NS_IMETHODIMP +xpcAccessibleTable::GetSelectedRowIndices(uint32_t* aRowsArraySize, + int32_t** aRowsArray) +{ + NS_ENSURE_ARG_POINTER(aRowsArraySize); + *aRowsArraySize = 0; + + NS_ENSURE_ARG_POINTER(aRowsArray); + *aRowsArray = 0; + + if (!Intl()) + return NS_ERROR_FAILURE; + + AutoTArray<uint32_t, XPC_TABLE_DEFAULT_SIZE> rowsArray; + Intl()->SelectedRowIndices(&rowsArray); + + *aRowsArraySize = rowsArray.Length(); + *aRowsArray = static_cast<int32_t*> + (moz_xmalloc(*aRowsArraySize * sizeof(int32_t))); + memcpy(*aRowsArray, rowsArray.Elements(), + *aRowsArraySize * sizeof(int32_t)); + + 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..36dd77e0a4 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleTable.h @@ -0,0 +1,96 @@ +/* -*- Mode: C++ final; tab-width: 2 final; indent-tabs-mode: nil final; 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 "xpcAccessibleGeneric.h" + +namespace mozilla { +namespace a11y { + +/** + * XPCOM wrapper around TableAccessible class. + */ +class xpcAccessibleTable : public xpcAccessibleGeneric, + public nsIAccessibleTable +{ +public: + explicit xpcAccessibleTable(Accessible* aIntl) : + xpcAccessibleGeneric(aIntl) { } + + xpcAccessibleTable(ProxyAccessible* aProxy, uint32_t aInterfaces) : + xpcAccessibleGeneric(aProxy, aInterfaces) {} + + NS_DECL_ISUPPORTS_INHERITED + + // nsIAccessibleTable + NS_IMETHOD GetCaption(nsIAccessible** aCaption) final override; + NS_IMETHOD GetSummary(nsAString& aSummary) final override; + NS_IMETHOD GetColumnCount(int32_t* aColumnCount) final override; + NS_IMETHOD GetRowCount(int32_t* aRowCount) final override; + NS_IMETHOD GetCellAt(int32_t aRowIndex, int32_t aColumnIndex, + nsIAccessible** aCell) final override; + NS_IMETHOD GetCellIndexAt(int32_t aRowIndex, int32_t aColumnIndex, + int32_t* aCellIndex) final override; + NS_IMETHOD GetColumnIndexAt(int32_t aCellIndex, int32_t* aColumnIndex) + final override; + NS_IMETHOD GetRowIndexAt(int32_t aCellIndex, int32_t* aRowIndex) + final override; + NS_IMETHOD GetRowAndColumnIndicesAt(int32_t aCellIndex, int32_t* aRowIndex, + int32_t* aColumnIndex) + final override; + NS_IMETHOD GetColumnExtentAt(int32_t row, int32_t column, + int32_t* aColumnExtent) final override; + NS_IMETHOD GetRowExtentAt(int32_t row, int32_t column, + int32_t* aRowExtent) final override; + NS_IMETHOD GetColumnDescription(int32_t aColIdx, nsAString& aDescription) + final override; + NS_IMETHOD GetRowDescription(int32_t aRowIdx, nsAString& aDescription) + final override; + NS_IMETHOD IsColumnSelected(int32_t aColIdx, bool* _retval) + final override; + NS_IMETHOD IsRowSelected(int32_t aRowIdx, bool* _retval) + final override; + NS_IMETHOD IsCellSelected(int32_t aRowIdx, int32_t aColIdx, bool* _retval) + final override; + NS_IMETHOD GetSelectedCellCount(uint32_t* aSelectedCellCount) + final override; + NS_IMETHOD GetSelectedColumnCount(uint32_t* aSelectedColumnCount) + final override; + NS_IMETHOD GetSelectedRowCount(uint32_t* aSelectedRowCount) + final override; + NS_IMETHOD GetSelectedCells(nsIArray** aSelectedCell) final override; + NS_IMETHOD GetSelectedCellIndices(uint32_t* aCellsArraySize, + int32_t** aCellsArray) + final override; + NS_IMETHOD GetSelectedColumnIndices(uint32_t* aColsArraySize, + int32_t** aColsArray) + final override; + NS_IMETHOD GetSelectedRowIndices(uint32_t* aRowsArraySize, + int32_t** aRowsArray) final override; + NS_IMETHOD SelectColumn(int32_t aColIdx) final override; + NS_IMETHOD SelectRow(int32_t aRowIdx) final override; + NS_IMETHOD UnselectColumn(int32_t aColIdx) final override; + NS_IMETHOD UnselectRow(int32_t aRowIdx) final override; + NS_IMETHOD IsProbablyForLayout(bool* aIsForLayout) final override; + +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..e507a88162 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleTableCell.cpp @@ -0,0 +1,161 @@ +/* -*- 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 "xpcAccessibleDocument.h" + +#include "nsComponentManagerUtils.h" +#include "nsIMutableArray.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])), + false); + } + + 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])), + false); + } + + 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..9a40f8e1a5 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleTableCell.h @@ -0,0 +1,62 @@ +/* -*- 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 override; + NS_IMETHOD GetColumnIndex(int32_t* aColIdx) final override; + NS_IMETHOD GetRowIndex(int32_t* aRowIdx) final override; + NS_IMETHOD GetColumnExtent(int32_t* aExtent) final override; + NS_IMETHOD GetRowExtent(int32_t* aExtent) final override; + NS_IMETHOD GetColumnHeaderCells(nsIArray** aHeaderCells) final override; + NS_IMETHOD GetRowHeaderCells(nsIArray** aHeaderCells) final override; + NS_IMETHOD IsSelected(bool* aSelected) final override; + +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..07a6ec6d36 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleTextRange.cpp @@ -0,0 +1,221 @@ +/* -*- 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 "xpcAccessibleDocument.h" + +#include "nsIMutableArray.h" +#include "nsComponentManagerUtils.h" +#include "nsQueryObject.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])), false); + + 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..3157077033 --- /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 "nsIAccessibleTextRange.h" +#include "TextRange.h" + +#include "mozilla/Move.h" +#include "nsCycleCollectionParticipant.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: + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_CYCLE_COLLECTION_CLASS(xpcAccessibleTextRange) + + NS_IMETHOD GetStartContainer(nsIAccessibleText** aAnchor) final override; + NS_IMETHOD GetStartOffset(int32_t* aOffset) final override; + NS_IMETHOD GetEndContainer(nsIAccessibleText** aAnchor) final override; + NS_IMETHOD GetEndOffset(int32_t* aOffset) final override; + NS_IMETHOD GetContainer(nsIAccessible** aContainer) final override; + NS_IMETHOD GetEmbeddedChildren(nsIArray** aList) final override; + NS_IMETHOD Compare(nsIAccessibleTextRange* aOtherRange, bool* aResult) final override; + NS_IMETHOD CompareEndPoints(uint32_t aEndPoint, + nsIAccessibleTextRange* aOtherRange, + uint32_t aOtherRangeEndPoint, + int32_t* aResult) final override; + NS_IMETHOD GetText(nsAString& aText) final override; + NS_IMETHOD GetBounds(nsIArray** aRectList) final override; + NS_IMETHOD Move(uint32_t aUnit, int32_t aCount) final override; + NS_IMETHOD MoveStart(uint32_t aUnit, int32_t aCount) final override; + NS_IMETHOD MoveEnd(uint32_t aUnit, int32_t aCount) final override; + NS_IMETHOD Normalize(uint32_t aUnit) final override; + NS_IMETHOD Crop(nsIAccessible* aContainer, bool* aSuccess) final override; + NS_IMETHOD FindText(const nsAString& aText, bool aIsBackward, bool aIsIgnoreCase, + nsIAccessibleTextRange** aRange) final override; + NS_IMETHOD FindAttr(uint32_t aAttr, nsIVariant* aVal, bool aIsBackward, + nsIAccessibleTextRange** aRange) final override; + NS_IMETHOD AddToSelection() final override; + NS_IMETHOD RemoveFromSelection() final override; + NS_IMETHOD Select() final override; + NS_IMETHOD ScrollIntoView(uint32_t aHow) final override; + + NS_DECLARE_STATIC_IID_ACCESSOR(NS_ACCESSIBLETEXTRANGE_IMPL_IID) + +private: + explicit xpcAccessibleTextRange(TextRange&& aRange) : + mRange(Forward<TextRange>(aRange)) {} + 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..f3628ff037 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleValue.cpp @@ -0,0 +1,133 @@ +/* -*- 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 { +#if defined(XP_WIN) + return NS_ERROR_NOT_IMPLEMENTED; +#else + value = Intl().AsProxy()->Step(); +#endif + } + + 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..740b512b89 --- /dev/null +++ b/accessible/xpcom/xpcAccessibleValue.h @@ -0,0 +1,43 @@ +/* -*- 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 override; + NS_IMETHOD GetMinimumValue(double* aValue) final override; + NS_IMETHOD GetCurrentValue(double* aValue) final override; + NS_IMETHOD SetCurrentValue(double aValue) final override; + NS_IMETHOD GetMinimumIncrement(double* aMinIncrement) final override; + +protected: + xpcAccessibleValue() { } + virtual ~xpcAccessibleValue() {} + +private: + AccessibleOrProxy Intl(); + + xpcAccessibleValue(const xpcAccessibleValue&) = delete; + xpcAccessibleValue& operator =(const xpcAccessibleValue&) = delete; +}; + +} // namespace a11y +} // namespace mozilla +#endif |