1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "XULElementAccessibles.h"
8 #include "LocalAccessible-inl.h"
9 #include "BaseAccessibles.h"
10 #include "DocAccessible-inl.h"
11 #include "nsAccUtils.h"
12 #include "nsCoreUtils.h"
13 #include "nsTextEquivUtils.h"
15 #include "mozilla/a11y/Role.h"
17 #include "TextUpdater.h"
23 #include "nsNameSpaceManager.h"
24 #include "nsNetUtil.h"
26 #include "nsXULElement.h"
28 using namespace mozilla::a11y
;
30 ////////////////////////////////////////////////////////////////////////////////
32 ////////////////////////////////////////////////////////////////////////////////
34 XULLabelAccessible::XULLabelAccessible(nsIContent
* aContent
,
36 : HyperTextAccessible(aContent
, aDoc
) {
37 mType
= eXULLabelType
;
40 void XULLabelAccessible::Shutdown() {
41 mValueTextLeaf
= nullptr;
42 HyperTextAccessible::Shutdown();
45 void XULLabelAccessible::DispatchClickEvent(nsIContent
* aContent
,
46 uint32_t aActionIndex
) const {
47 // Bug 1578140: For labels inside buttons, The base implementation of
48 // DispatchClickEvent doesn't fire a command event on the button.
49 RefPtr
<nsXULElement
> el
= nsXULElement::FromNodeOrNull(aContent
);
51 el
->Click(mozilla::dom::CallerType::System
);
55 ENameValueFlag
XULLabelAccessible::NativeName(nsString
& aName
) const {
56 // if the value attr doesn't exist, the screen reader must get the accessible
57 // text from the accessible text interface or from the children
58 if (mValueTextLeaf
) return mValueTextLeaf
->Name(aName
);
60 return LocalAccessible::NativeName(aName
);
63 role
XULLabelAccessible::NativeRole() const { return roles::LABEL
; }
65 uint64_t XULLabelAccessible::NativeState() const {
66 // Labels and description have read only state
67 // They are not focusable or selectable
68 return HyperTextAccessible::NativeState() | states::READONLY
;
71 Relation
XULLabelAccessible::RelationByType(RelationType aType
) const {
72 Relation rel
= HyperTextAccessible::RelationByType(aType
);
74 // The label for xul:groupbox is generated from the first xul:label
75 if (aType
== RelationType::LABEL_FOR
) {
76 LocalAccessible
* parent
= LocalParent();
77 if (parent
&& parent
->Role() == roles::GROUPING
&&
78 parent
->LocalChildAt(0) == this) {
79 nsIContent
* parentContent
= parent
->GetContent();
80 if (parentContent
&& parentContent
->IsXULElement(nsGkAtoms::groupbox
)) {
81 rel
.AppendTarget(parent
);
89 void XULLabelAccessible::UpdateLabelValue(const nsString
& aValue
) {
91 if (logging::IsEnabled(logging::eText
)) {
92 logging::MsgBegin("TEXT", "text may be changed (xul:label @value update)");
93 logging::Node("container", mContent
);
94 logging::MsgEntry("old text '%s'",
95 NS_ConvertUTF16toUTF8(mValueTextLeaf
->Text()).get());
96 logging::MsgEntry("new text: '%s'", NS_ConvertUTF16toUTF8(aValue
).get());
101 TextUpdater::Run(mDoc
, mValueTextLeaf
, aValue
);
104 ////////////////////////////////////////////////////////////////////////////////
105 // XULLabelTextLeafAccessible
106 ////////////////////////////////////////////////////////////////////////////////
108 role
XULLabelTextLeafAccessible::NativeRole() const { return roles::TEXT_LEAF
; }
110 uint64_t XULLabelTextLeafAccessible::NativeState() const {
111 return TextLeafAccessible::NativeState() | states::READONLY
;
114 ////////////////////////////////////////////////////////////////////////////////
115 // XULTooltipAccessible
116 ////////////////////////////////////////////////////////////////////////////////
118 XULTooltipAccessible::XULTooltipAccessible(nsIContent
* aContent
,
120 : LeafAccessible(aContent
, aDoc
) {
121 mType
= eXULTooltipType
;
124 uint64_t XULTooltipAccessible::NativeState() const {
125 return LeafAccessible::NativeState() | states::READONLY
;
128 role
XULTooltipAccessible::NativeRole() const { return roles::TOOLTIP
; }
130 ////////////////////////////////////////////////////////////////////////////////
132 ////////////////////////////////////////////////////////////////////////////////
134 XULLinkAccessible::XULLinkAccessible(nsIContent
* aContent
, DocAccessible
* aDoc
)
135 : XULLabelAccessible(aContent
, aDoc
) {}
137 XULLinkAccessible::~XULLinkAccessible() {}
139 ////////////////////////////////////////////////////////////////////////////////
140 // XULLinkAccessible: LocalAccessible
142 void XULLinkAccessible::Value(nsString
& aValue
) const {
145 mContent
->AsElement()->GetAttr(nsGkAtoms::href
, aValue
);
148 ENameValueFlag
XULLinkAccessible::NativeName(nsString
& aName
) const {
149 mContent
->AsElement()->GetAttr(nsGkAtoms::value
, aName
);
150 if (!aName
.IsEmpty()) return eNameOK
;
152 nsTextEquivUtils::GetNameFromSubtree(this, aName
);
153 return aName
.IsEmpty() ? eNameOK
: eNameFromSubtree
;
156 role
XULLinkAccessible::NativeRole() const { return roles::LINK
; }
158 uint64_t XULLinkAccessible::NativeLinkState() const { return states::LINKED
; }
160 bool XULLinkAccessible::HasPrimaryAction() const { return true; }
162 void XULLinkAccessible::ActionNameAt(uint8_t aIndex
, nsAString
& aName
) {
165 if (aIndex
== eAction_Jump
) aName
.AssignLiteral("jump");
168 ////////////////////////////////////////////////////////////////////////////////
169 // XULLinkAccessible: HyperLinkAccessible
171 bool XULLinkAccessible::IsLink() const {
172 // Expose HyperLinkAccessible unconditionally.
176 uint32_t XULLinkAccessible::StartOffset() {
177 // If XUL link accessible is not contained by hypertext accessible then
178 // start offset matches index in parent because the parent doesn't contains
180 // XXX: accessible parent of XUL link accessible should be a hypertext
182 if (LocalAccessible::IsLink()) return LocalAccessible::StartOffset();
183 return IndexInParent();
186 uint32_t XULLinkAccessible::EndOffset() {
187 if (LocalAccessible::IsLink()) return LocalAccessible::EndOffset();
188 return IndexInParent() + 1;
191 already_AddRefed
<nsIURI
> XULLinkAccessible::AnchorURIAt(
192 uint32_t aAnchorIndex
) const {
193 if (aAnchorIndex
!= 0) return nullptr;
196 mContent
->AsElement()->GetAttr(nsGkAtoms::href
, href
);
198 dom::Document
* document
= mContent
->OwnerDoc();
200 nsCOMPtr
<nsIURI
> anchorURI
;
201 NS_NewURI(getter_AddRefs(anchorURI
), href
,
202 document
->GetDocumentCharacterSet(), mContent
->GetBaseURI());
204 return anchorURI
.forget();