|
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/. */ |
|
5 |
|
6 #include "ImageAccessible.h" |
|
7 |
|
8 #include "nsAccUtils.h" |
|
9 #include "Role.h" |
|
10 #include "AccIterator.h" |
|
11 #include "States.h" |
|
12 |
|
13 #include "imgIContainer.h" |
|
14 #include "imgIRequest.h" |
|
15 #include "nsGenericHTMLElement.h" |
|
16 #include "nsIDocument.h" |
|
17 #include "nsIImageLoadingContent.h" |
|
18 #include "nsIPresShell.h" |
|
19 #include "nsIServiceManager.h" |
|
20 #include "nsIDOMHTMLImageElement.h" |
|
21 #include "nsIPersistentProperties2.h" |
|
22 #include "nsPIDOMWindow.h" |
|
23 #include "nsIURI.h" |
|
24 |
|
25 using namespace mozilla::a11y; |
|
26 |
|
27 //////////////////////////////////////////////////////////////////////////////// |
|
28 // ImageAccessible |
|
29 //////////////////////////////////////////////////////////////////////////////// |
|
30 |
|
31 ImageAccessible:: |
|
32 ImageAccessible(nsIContent* aContent, DocAccessible* aDoc) : |
|
33 LinkableAccessible(aContent, aDoc) |
|
34 { |
|
35 mType = eImageType; |
|
36 } |
|
37 |
|
38 NS_IMPL_ISUPPORTS_INHERITED(ImageAccessible, Accessible, |
|
39 nsIAccessibleImage) |
|
40 |
|
41 //////////////////////////////////////////////////////////////////////////////// |
|
42 // Accessible public |
|
43 |
|
44 uint64_t |
|
45 ImageAccessible::NativeState() |
|
46 { |
|
47 // The state is a bitfield, get our inherited state, then logically OR it with |
|
48 // states::ANIMATED if this is an animated image. |
|
49 |
|
50 uint64_t state = LinkableAccessible::NativeState(); |
|
51 |
|
52 nsCOMPtr<nsIImageLoadingContent> content(do_QueryInterface(mContent)); |
|
53 nsCOMPtr<imgIRequest> imageRequest; |
|
54 |
|
55 if (content) |
|
56 content->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, |
|
57 getter_AddRefs(imageRequest)); |
|
58 |
|
59 nsCOMPtr<imgIContainer> imgContainer; |
|
60 if (imageRequest) |
|
61 imageRequest->GetImage(getter_AddRefs(imgContainer)); |
|
62 |
|
63 if (imgContainer) { |
|
64 bool animated; |
|
65 imgContainer->GetAnimated(&animated); |
|
66 if (animated) |
|
67 state |= states::ANIMATED; |
|
68 } |
|
69 |
|
70 return state; |
|
71 } |
|
72 |
|
73 ENameValueFlag |
|
74 ImageAccessible::NativeName(nsString& aName) |
|
75 { |
|
76 bool hasAltAttrib = |
|
77 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName); |
|
78 if (!aName.IsEmpty()) |
|
79 return eNameOK; |
|
80 |
|
81 ENameValueFlag nameFlag = Accessible::NativeName(aName); |
|
82 if (!aName.IsEmpty()) |
|
83 return nameFlag; |
|
84 |
|
85 // No accessible name but empty 'alt' attribute is present. If further name |
|
86 // computation algorithm doesn't provide non empty name then it means |
|
87 // an empty 'alt' attribute was used to indicate a decorative image (see |
|
88 // Accessible::Name() method for details). |
|
89 return hasAltAttrib ? eNoNameOnPurpose : eNameOK; |
|
90 } |
|
91 |
|
92 role |
|
93 ImageAccessible::NativeRole() |
|
94 { |
|
95 return roles::GRAPHIC; |
|
96 } |
|
97 |
|
98 //////////////////////////////////////////////////////////////////////////////// |
|
99 // nsIAccessible |
|
100 |
|
101 uint8_t |
|
102 ImageAccessible::ActionCount() |
|
103 { |
|
104 uint8_t actionCount = LinkableAccessible::ActionCount(); |
|
105 return HasLongDesc() ? actionCount + 1 : actionCount; |
|
106 } |
|
107 |
|
108 NS_IMETHODIMP |
|
109 ImageAccessible::GetActionName(uint8_t aIndex, nsAString& aName) |
|
110 { |
|
111 aName.Truncate(); |
|
112 |
|
113 if (IsDefunct()) |
|
114 return NS_ERROR_FAILURE; |
|
115 |
|
116 if (IsLongDescIndex(aIndex) && HasLongDesc()) { |
|
117 aName.AssignLiteral("showlongdesc"); |
|
118 return NS_OK; |
|
119 } |
|
120 return LinkableAccessible::GetActionName(aIndex, aName); |
|
121 } |
|
122 |
|
123 NS_IMETHODIMP |
|
124 ImageAccessible::DoAction(uint8_t aIndex) |
|
125 { |
|
126 if (IsDefunct()) |
|
127 return NS_ERROR_FAILURE; |
|
128 |
|
129 // Get the long description uri and open in a new window. |
|
130 if (!IsLongDescIndex(aIndex)) |
|
131 return LinkableAccessible::DoAction(aIndex); |
|
132 |
|
133 nsCOMPtr<nsIURI> uri = GetLongDescURI(); |
|
134 if (!uri) |
|
135 return NS_ERROR_INVALID_ARG; |
|
136 |
|
137 nsAutoCString utf8spec; |
|
138 uri->GetSpec(utf8spec); |
|
139 NS_ConvertUTF8toUTF16 spec(utf8spec); |
|
140 |
|
141 nsIDocument* document = mContent->OwnerDoc(); |
|
142 nsCOMPtr<nsPIDOMWindow> piWindow = document->GetWindow(); |
|
143 nsCOMPtr<nsIDOMWindow> win = do_QueryInterface(piWindow); |
|
144 NS_ENSURE_STATE(win); |
|
145 |
|
146 nsCOMPtr<nsIDOMWindow> tmp; |
|
147 return win->Open(spec, EmptyString(), EmptyString(), |
|
148 getter_AddRefs(tmp)); |
|
149 } |
|
150 |
|
151 //////////////////////////////////////////////////////////////////////////////// |
|
152 // nsIAccessibleImage |
|
153 |
|
154 NS_IMETHODIMP |
|
155 ImageAccessible::GetImagePosition(uint32_t aCoordType, int32_t* aX, int32_t* aY) |
|
156 { |
|
157 int32_t width, height; |
|
158 nsresult rv = GetBounds(aX, aY, &width, &height); |
|
159 if (NS_FAILED(rv)) |
|
160 return rv; |
|
161 |
|
162 nsAccUtils::ConvertScreenCoordsTo(aX, aY, aCoordType, this); |
|
163 return NS_OK; |
|
164 } |
|
165 |
|
166 NS_IMETHODIMP |
|
167 ImageAccessible::GetImageSize(int32_t* aWidth, int32_t* aHeight) |
|
168 { |
|
169 int32_t x, y; |
|
170 return GetBounds(&x, &y, aWidth, aHeight); |
|
171 } |
|
172 |
|
173 // Accessible |
|
174 already_AddRefed<nsIPersistentProperties> |
|
175 ImageAccessible::NativeAttributes() |
|
176 { |
|
177 nsCOMPtr<nsIPersistentProperties> attributes = |
|
178 LinkableAccessible::NativeAttributes(); |
|
179 |
|
180 nsAutoString src; |
|
181 mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src); |
|
182 if (!src.IsEmpty()) |
|
183 nsAccUtils::SetAccAttr(attributes, nsGkAtoms::src, src); |
|
184 |
|
185 return attributes.forget(); |
|
186 } |
|
187 |
|
188 //////////////////////////////////////////////////////////////////////////////// |
|
189 // Private methods |
|
190 |
|
191 already_AddRefed<nsIURI> |
|
192 ImageAccessible::GetLongDescURI() const |
|
193 { |
|
194 if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::longdesc)) { |
|
195 nsGenericHTMLElement* element = |
|
196 nsGenericHTMLElement::FromContent(mContent); |
|
197 if (element) { |
|
198 nsCOMPtr<nsIURI> uri; |
|
199 element->GetURIAttr(nsGkAtoms::longdesc, nullptr, getter_AddRefs(uri)); |
|
200 return uri.forget(); |
|
201 } |
|
202 } |
|
203 |
|
204 DocAccessible* document = Document(); |
|
205 if (document) { |
|
206 IDRefsIterator iter(document, mContent, nsGkAtoms::aria_describedby); |
|
207 while (nsIContent* target = iter.NextElem()) { |
|
208 if ((target->IsHTML(nsGkAtoms::a) || target->IsHTML(nsGkAtoms::area)) && |
|
209 target->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) { |
|
210 nsGenericHTMLElement* element = |
|
211 nsGenericHTMLElement::FromContent(target); |
|
212 |
|
213 nsCOMPtr<nsIURI> uri; |
|
214 element->GetURIAttr(nsGkAtoms::href, nullptr, getter_AddRefs(uri)); |
|
215 return uri.forget(); |
|
216 } |
|
217 } |
|
218 } |
|
219 |
|
220 return nullptr; |
|
221 } |
|
222 |
|
223 bool |
|
224 ImageAccessible::IsLongDescIndex(uint8_t aIndex) |
|
225 { |
|
226 return aIndex == LinkableAccessible::ActionCount(); |
|
227 } |
|
228 |