AX: aria-hidden on container does not hide descendant popup buttons
[WebKit-https.git] / Source / WebCore / accessibility / AccessibilityMediaControls.cpp
1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29
30 #include "config.h"
31
32 #if ENABLE(VIDEO)
33
34 #include "AccessibilityMediaControls.h"
35
36 #include "AXObjectCache.h"
37 #include "HTMLInputElement.h"
38 #include "HTMLMediaElement.h"
39 #include "HTMLNames.h"
40 #include "LocalizedStrings.h"
41 #include "MediaControlElements.h"
42 #include "RenderObject.h"
43 #include "RenderSlider.h"
44
45 namespace WebCore {
46
47 using namespace HTMLNames;
48
49
50 AccessibilityMediaControl::AccessibilityMediaControl(RenderObject* renderer)
51     : AccessibilityRenderObject(renderer)
52 {
53 }
54
55 PassRefPtr<AccessibilityObject> AccessibilityMediaControl::create(RenderObject* renderer)
56 {
57     ASSERT(renderer->node());
58
59     switch (mediaControlElementType(renderer->node())) {
60     case MediaSlider:
61         return AccessibilityMediaTimeline::create(renderer);
62
63     case MediaCurrentTimeDisplay:
64     case MediaTimeRemainingDisplay:
65         return AccessibilityMediaTimeDisplay::create(renderer);
66
67     case MediaControlsPanel:
68         return AccessibilityMediaControlsContainer::create(renderer);
69
70     default:
71         return adoptRef(new AccessibilityMediaControl(renderer));
72     }
73 }
74
75 MediaControlElementType AccessibilityMediaControl::controlType() const
76 {
77     if (!renderer() || !renderer()->node())
78         return MediaTimelineContainer; // Timeline container is not accessible.
79
80     return mediaControlElementType(renderer()->node());
81 }
82
83 String AccessibilityMediaControl::controlTypeName() const
84 {
85     DEFINE_STATIC_LOCAL(const String, mediaEnterFullscreenButtonName, (ASCIILiteral("EnterFullscreenButton")));
86     DEFINE_STATIC_LOCAL(const String, mediaExitFullscreenButtonName, (ASCIILiteral("ExitFullscreenButton")));
87     DEFINE_STATIC_LOCAL(const String, mediaMuteButtonName, (ASCIILiteral("MuteButton")));
88     DEFINE_STATIC_LOCAL(const String, mediaPlayButtonName, (ASCIILiteral("PlayButton")));
89     DEFINE_STATIC_LOCAL(const String, mediaSeekBackButtonName, (ASCIILiteral("SeekBackButton")));
90     DEFINE_STATIC_LOCAL(const String, mediaSeekForwardButtonName, (ASCIILiteral("SeekForwardButton")));
91     DEFINE_STATIC_LOCAL(const String, mediaRewindButtonName, (ASCIILiteral("RewindButton")));
92     DEFINE_STATIC_LOCAL(const String, mediaReturnToRealtimeButtonName, (ASCIILiteral("ReturnToRealtimeButton")));
93     DEFINE_STATIC_LOCAL(const String, mediaUnMuteButtonName, (ASCIILiteral("UnMuteButton")));
94     DEFINE_STATIC_LOCAL(const String, mediaPauseButtonName, (ASCIILiteral("PauseButton")));
95     DEFINE_STATIC_LOCAL(const String, mediaStatusDisplayName, (ASCIILiteral("StatusDisplay")));
96     DEFINE_STATIC_LOCAL(const String, mediaCurrentTimeDisplay, (ASCIILiteral("CurrentTimeDisplay")));
97     DEFINE_STATIC_LOCAL(const String, mediaTimeRemainingDisplay, (ASCIILiteral("TimeRemainingDisplay")));
98     DEFINE_STATIC_LOCAL(const String, mediaShowClosedCaptionsButtonName, (ASCIILiteral("ShowClosedCaptionsButton")));
99     DEFINE_STATIC_LOCAL(const String, mediaHideClosedCaptionsButtonName, (ASCIILiteral("HideClosedCaptionsButton")));
100
101     switch (controlType()) {
102     case MediaEnterFullscreenButton:
103         return mediaEnterFullscreenButtonName;
104     case MediaExitFullscreenButton:
105         return mediaExitFullscreenButtonName;
106     case MediaMuteButton:
107         return mediaMuteButtonName;
108     case MediaPlayButton:
109         return mediaPlayButtonName;
110     case MediaSeekBackButton:
111         return mediaSeekBackButtonName;
112     case MediaSeekForwardButton:
113         return mediaSeekForwardButtonName;
114     case MediaRewindButton:
115         return mediaRewindButtonName;
116     case MediaReturnToRealtimeButton:
117         return mediaReturnToRealtimeButtonName;
118     case MediaUnMuteButton:
119         return mediaUnMuteButtonName;
120     case MediaPauseButton:
121         return mediaPauseButtonName;
122     case MediaStatusDisplay:
123         return mediaStatusDisplayName;
124     case MediaCurrentTimeDisplay:
125         return mediaCurrentTimeDisplay;
126     case MediaTimeRemainingDisplay:
127         return mediaTimeRemainingDisplay;
128     case MediaShowClosedCaptionsButton:
129         return mediaShowClosedCaptionsButtonName;
130     case MediaHideClosedCaptionsButton:
131         return mediaHideClosedCaptionsButtonName;
132
133     default:
134         break;
135     }
136
137     return String();
138 }
139
140 void AccessibilityMediaControl::accessibilityText(Vector<AccessibilityText>& textOrder)
141 {
142     String description = accessibilityDescription();
143     if (!description.isEmpty())
144         textOrder.append(AccessibilityText(description, AlternativeText));
145
146     String title = this->title();
147     if (!title.isEmpty())
148         textOrder.append(AccessibilityText(title, AlternativeText));
149
150     String helptext = helpText();
151     if (!helptext.isEmpty())
152         textOrder.append(AccessibilityText(helptext, HelpText));
153 }
154     
155
156 String AccessibilityMediaControl::title() const
157 {
158     DEFINE_STATIC_LOCAL(const String, controlsPanel, (ASCIILiteral("ControlsPanel")));
159
160     if (controlType() == MediaControlsPanel)
161         return localizedMediaControlElementString(controlsPanel);
162
163     return AccessibilityRenderObject::title();
164 }
165
166 String AccessibilityMediaControl::accessibilityDescription() const
167 {
168     return localizedMediaControlElementString(controlTypeName());
169 }
170
171 String AccessibilityMediaControl::helpText() const
172 {
173     return localizedMediaControlElementHelpText(controlTypeName());
174 }
175
176 bool AccessibilityMediaControl::computeAccessibilityIsIgnored() const
177 {
178     if (!m_renderer || !m_renderer->style() || m_renderer->style()->visibility() != VISIBLE || controlType() == MediaTimelineContainer)
179         return true;
180
181     return accessibilityIsIgnoredByDefault();
182 }
183
184 AccessibilityRole AccessibilityMediaControl::roleValue() const
185 {
186     switch (controlType()) {
187     case MediaEnterFullscreenButton:
188     case MediaExitFullscreenButton:
189     case MediaMuteButton:
190     case MediaPlayButton:
191     case MediaSeekBackButton:
192     case MediaSeekForwardButton:
193     case MediaRewindButton:
194     case MediaReturnToRealtimeButton:
195     case MediaUnMuteButton:
196     case MediaPauseButton:
197     case MediaShowClosedCaptionsButton:
198     case MediaHideClosedCaptionsButton:
199         return ButtonRole;
200
201     case MediaStatusDisplay:
202         return StaticTextRole;
203
204     case MediaTimelineContainer:
205         return GroupRole;
206
207     default:
208         break;
209     }
210
211     return UnknownRole;
212 }
213
214
215
216 //
217 // AccessibilityMediaControlsContainer
218
219 AccessibilityMediaControlsContainer::AccessibilityMediaControlsContainer(RenderObject* renderer)
220     : AccessibilityMediaControl(renderer)
221 {
222 }
223
224 PassRefPtr<AccessibilityObject> AccessibilityMediaControlsContainer::create(RenderObject* renderer)
225 {
226     return adoptRef(new AccessibilityMediaControlsContainer(renderer));
227 }
228
229 String AccessibilityMediaControlsContainer::accessibilityDescription() const
230 {
231     return localizedMediaControlElementString(elementTypeName());
232 }
233
234 String AccessibilityMediaControlsContainer::helpText() const
235 {
236     return localizedMediaControlElementHelpText(elementTypeName());
237 }
238
239 bool AccessibilityMediaControlsContainer::controllingVideoElement() const
240 {
241     if (!m_renderer->node())
242         return true;
243
244     MediaControlTimeDisplayElement* element = static_cast<MediaControlTimeDisplayElement*>(m_renderer->node());
245
246     return toParentMediaElement(element)->isVideo();
247 }
248
249 const String AccessibilityMediaControlsContainer::elementTypeName() const
250 {
251     DEFINE_STATIC_LOCAL(const String, videoElement, (ASCIILiteral("VideoElement")));
252     DEFINE_STATIC_LOCAL(const String, audioElement, (ASCIILiteral("AudioElement")));
253
254     if (controllingVideoElement())
255         return videoElement;
256     return audioElement;
257 }
258
259 bool AccessibilityMediaControlsContainer::computeAccessibilityIsIgnored() const
260 {
261     return accessibilityIsIgnoredByDefault();
262 }
263
264 //
265 // AccessibilityMediaTimeline
266
267 AccessibilityMediaTimeline::AccessibilityMediaTimeline(RenderObject* renderer)
268     : AccessibilitySlider(renderer)
269 {
270 }
271
272 PassRefPtr<AccessibilityObject> AccessibilityMediaTimeline::create(RenderObject* renderer)
273 {
274     return adoptRef(new AccessibilityMediaTimeline(renderer));
275 }
276
277 String AccessibilityMediaTimeline::valueDescription() const
278 {
279     Node* node = m_renderer->node();
280     if (!node->hasTagName(inputTag))
281         return String();
282
283     float time = static_cast<HTMLInputElement*>(node)->value().toFloat();
284     return localizedMediaTimeDescription(time);
285 }
286
287 String AccessibilityMediaTimeline::helpText() const
288 {
289     DEFINE_STATIC_LOCAL(const String, slider, (ASCIILiteral("Slider")));
290     return localizedMediaControlElementHelpText(slider);
291 }
292
293
294 //
295 // AccessibilityMediaTimeDisplay
296
297 AccessibilityMediaTimeDisplay::AccessibilityMediaTimeDisplay(RenderObject* renderer)
298     : AccessibilityMediaControl(renderer)
299 {
300 }
301
302 PassRefPtr<AccessibilityObject> AccessibilityMediaTimeDisplay::create(RenderObject* renderer)
303 {
304     return adoptRef(new AccessibilityMediaTimeDisplay(renderer));
305 }
306
307 bool AccessibilityMediaTimeDisplay::computeAccessibilityIsIgnored() const
308 {
309     if (!m_renderer || !m_renderer->style() || m_renderer->style()->visibility() != VISIBLE)
310         return true;
311
312     if (!m_renderer->style()->width().value())
313         return true;
314     
315     return accessibilityIsIgnoredByDefault();
316 }
317
318 String AccessibilityMediaTimeDisplay::accessibilityDescription() const
319 {
320     DEFINE_STATIC_LOCAL(const String, currentTimeDisplay, (ASCIILiteral("CurrentTimeDisplay")));
321     DEFINE_STATIC_LOCAL(const String, timeRemainingDisplay, (ASCIILiteral("TimeRemainingDisplay")));
322
323     if (controlType() == MediaCurrentTimeDisplay)
324         return localizedMediaControlElementString(currentTimeDisplay);
325
326     return localizedMediaControlElementString(timeRemainingDisplay);
327 }
328
329 String AccessibilityMediaTimeDisplay::stringValue() const
330 {
331     if (!m_renderer || !m_renderer->node())
332         return String();
333
334     MediaControlTimeDisplayElement* element = static_cast<MediaControlTimeDisplayElement*>(m_renderer->node());
335     float time = element->currentValue();
336     return localizedMediaTimeDescription(fabsf(time));
337 }
338
339 } // namespace WebCore
340
341 #endif // ENABLE(VIDEO)