Line data Source code
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 "HTMLImageMapAccessible.h"
7 :
8 : #include "ARIAMap.h"
9 : #include "nsAccUtils.h"
10 : #include "DocAccessible-inl.h"
11 : #include "Role.h"
12 :
13 : #include "nsIDOMHTMLCollection.h"
14 : #include "nsIServiceManager.h"
15 : #include "nsIDOMElement.h"
16 : #include "nsIDOMHTMLAreaElement.h"
17 : #include "nsIFrame.h"
18 : #include "nsImageFrame.h"
19 : #include "nsImageMap.h"
20 : #include "nsIURI.h"
21 :
22 : using namespace mozilla::a11y;
23 :
24 : ////////////////////////////////////////////////////////////////////////////////
25 : // HTMLImageMapAccessible
26 : ////////////////////////////////////////////////////////////////////////////////
27 :
28 0 : HTMLImageMapAccessible::
29 0 : HTMLImageMapAccessible(nsIContent* aContent, DocAccessible* aDoc) :
30 0 : ImageAccessibleWrap(aContent, aDoc)
31 : {
32 0 : mType = eImageMapType;
33 :
34 0 : UpdateChildAreas(false);
35 0 : }
36 :
37 : ////////////////////////////////////////////////////////////////////////////////
38 : // HTMLImageMapAccessible: nsISupports
39 :
40 0 : NS_IMPL_ISUPPORTS_INHERITED0(HTMLImageMapAccessible, ImageAccessible)
41 :
42 : ////////////////////////////////////////////////////////////////////////////////
43 : // HTMLImageMapAccessible: Accessible public
44 :
45 : role
46 0 : HTMLImageMapAccessible::NativeRole()
47 : {
48 0 : return roles::IMAGE_MAP;
49 : }
50 :
51 : ////////////////////////////////////////////////////////////////////////////////
52 : // HTMLImageMapAccessible: HyperLinkAccessible
53 :
54 : uint32_t
55 0 : HTMLImageMapAccessible::AnchorCount()
56 : {
57 0 : return ChildCount();
58 : }
59 :
60 : Accessible*
61 0 : HTMLImageMapAccessible::AnchorAt(uint32_t aAnchorIndex)
62 : {
63 0 : return GetChildAt(aAnchorIndex);
64 : }
65 :
66 : already_AddRefed<nsIURI>
67 0 : HTMLImageMapAccessible::AnchorURIAt(uint32_t aAnchorIndex)
68 : {
69 0 : Accessible* area = GetChildAt(aAnchorIndex);
70 0 : if (!area)
71 0 : return nullptr;
72 :
73 0 : nsIContent* linkContent = area->GetContent();
74 0 : return linkContent ? linkContent->GetHrefURI() : nullptr;
75 : }
76 :
77 : ////////////////////////////////////////////////////////////////////////////////
78 : // HTMLImageMapAccessible: public
79 :
80 : void
81 0 : HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
82 : {
83 0 : nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame());
84 :
85 : // If image map is not initialized yet then we trigger one time more later.
86 0 : nsImageMap* imageMapObj = imageFrame->GetExistingImageMap();
87 0 : if (!imageMapObj)
88 0 : return;
89 :
90 0 : TreeMutation mt(this, TreeMutation::kNoEvents & !aDoFireEvents);
91 :
92 : // Remove areas that are not a valid part of the image map anymore.
93 0 : for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) {
94 0 : Accessible* area = mChildren.ElementAt(childIdx);
95 0 : if (area->GetContent()->GetPrimaryFrame())
96 0 : continue;
97 :
98 0 : mt.BeforeRemoval(area);
99 0 : RemoveChild(area);
100 : }
101 :
102 : // Insert new areas into the tree.
103 0 : uint32_t areaElmCount = imageMapObj->AreaCount();
104 0 : for (uint32_t idx = 0; idx < areaElmCount; idx++) {
105 0 : nsIContent* areaContent = imageMapObj->GetAreaAt(idx);
106 0 : Accessible* area = mChildren.SafeElementAt(idx);
107 0 : if (!area || area->GetContent() != areaContent) {
108 0 : RefPtr<Accessible> area = new HTMLAreaAccessible(areaContent, mDoc);
109 0 : mDoc->BindToDocument(area, aria::GetRoleMap(areaContent->AsElement()));
110 :
111 0 : if (!InsertChildAt(idx, area)) {
112 0 : mDoc->UnbindFromDocument(area);
113 0 : break;
114 : }
115 :
116 0 : mt.AfterInsertion(area);
117 : }
118 : }
119 :
120 0 : mt.Done();
121 : }
122 :
123 : Accessible*
124 0 : HTMLImageMapAccessible::GetChildAccessibleFor(const nsINode* aNode) const
125 : {
126 0 : uint32_t length = mChildren.Length();
127 0 : for (uint32_t i = 0; i < length; i++) {
128 0 : Accessible* area = mChildren[i];
129 0 : if (area->GetContent() == aNode)
130 0 : return area;
131 : }
132 :
133 0 : return nullptr;
134 : }
135 :
136 : ////////////////////////////////////////////////////////////////////////////////
137 : // HTMLAreaAccessible
138 : ////////////////////////////////////////////////////////////////////////////////
139 :
140 0 : HTMLAreaAccessible::
141 0 : HTMLAreaAccessible(nsIContent* aContent, DocAccessible* aDoc) :
142 0 : HTMLLinkAccessible(aContent, aDoc)
143 : {
144 : // Make HTML area DOM element not accessible. HTML image map accessible
145 : // manages its tree itself.
146 0 : mStateFlags |= eNotNodeMapEntry;
147 0 : }
148 :
149 : ////////////////////////////////////////////////////////////////////////////////
150 : // HTMLAreaAccessible: Accessible
151 :
152 : ENameValueFlag
153 0 : HTMLAreaAccessible::NativeName(nsString& aName)
154 : {
155 0 : ENameValueFlag nameFlag = Accessible::NativeName(aName);
156 0 : if (!aName.IsEmpty())
157 0 : return nameFlag;
158 :
159 0 : if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
160 0 : Value(aName);
161 :
162 0 : return eNameOK;
163 : }
164 :
165 : void
166 0 : HTMLAreaAccessible::Description(nsString& aDescription)
167 : {
168 0 : aDescription.Truncate();
169 :
170 : // Still to do - follow IE's standard here
171 0 : nsCOMPtr<nsIDOMHTMLAreaElement> area(do_QueryInterface(mContent));
172 0 : if (area)
173 0 : area->GetShape(aDescription);
174 0 : }
175 :
176 : ////////////////////////////////////////////////////////////////////////////////
177 : // HTMLAreaAccessible: Accessible public
178 :
179 : Accessible*
180 0 : HTMLAreaAccessible::ChildAtPoint(int32_t aX, int32_t aY,
181 : EWhichChildAtPoint aWhichChild)
182 : {
183 : // Don't walk into area accessibles.
184 0 : return this;
185 : }
186 :
187 : ////////////////////////////////////////////////////////////////////////////////
188 : // HTMLImageMapAccessible: HyperLinkAccessible
189 :
190 : uint32_t
191 0 : HTMLAreaAccessible::StartOffset()
192 : {
193 : // Image map accessible is not hypertext accessible therefore
194 : // StartOffset/EndOffset implementations of Accessible doesn't work here.
195 : // We return index in parent because image map contains area links only which
196 : // are embedded objects.
197 : // XXX: image map should be a hypertext accessible.
198 0 : return IndexInParent();
199 : }
200 :
201 : uint32_t
202 0 : HTMLAreaAccessible::EndOffset()
203 : {
204 0 : return IndexInParent() + 1;
205 : }
206 :
207 : nsRect
208 0 : HTMLAreaAccessible::RelativeBounds(nsIFrame** aBoundingFrame) const
209 : {
210 0 : nsIFrame* frame = GetFrame();
211 0 : if (!frame)
212 0 : return nsRect();
213 :
214 0 : nsImageFrame* imageFrame = do_QueryFrame(frame);
215 0 : nsImageMap* map = imageFrame->GetImageMap();
216 :
217 0 : nsRect bounds;
218 0 : nsresult rv = map->GetBoundsForAreaContent(mContent, bounds);
219 0 : if (NS_FAILED(rv))
220 0 : return nsRect();
221 :
222 : // XXX Areas are screwy; they return their rects as a pair of points, one pair
223 : // stored into the width and height.
224 0 : *aBoundingFrame = frame;
225 0 : bounds.width -= bounds.x;
226 0 : bounds.height -= bounds.y;
227 0 : return bounds;
228 : }
|