AX: move isIgnored caching to AXObject
[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 false;
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
260 //
261 // AccessibilityMediaTimeline
262
263 AccessibilityMediaTimeline::AccessibilityMediaTimeline(RenderObject* renderer)
264     : AccessibilitySlider(renderer)
265 {
266 }
267
268 PassRefPtr<AccessibilityObject> AccessibilityMediaTimeline::create(RenderObject* renderer)
269 {
270     return adoptRef(new AccessibilityMediaTimeline(renderer));
271 }
272
273 String AccessibilityMediaTimeline::valueDescription() const
274 {
275     Node* node = m_renderer->node();
276     if (!node->hasTagName(inputTag))
277         return String();
278
279     float time = static_cast<HTMLInputElement*>(node)->value().toFloat();
280     return localizedMediaTimeDescription(time);
281 }
282
283 String AccessibilityMediaTimeline::helpText() const
284 {
285     DEFINE_STATIC_LOCAL(const String, slider, (ASCIILiteral("Slider")));
286     return localizedMediaControlElementHelpText(slider);
287 }
288
289
290 //
291 // AccessibilityMediaTimeDisplay
292
293 AccessibilityMediaTimeDisplay::AccessibilityMediaTimeDisplay(RenderObject* renderer)
294     : AccessibilityMediaControl(renderer)
295 {
296 }
297
298 PassRefPtr<AccessibilityObject> AccessibilityMediaTimeDisplay::create(RenderObject* renderer)
299 {
300     return adoptRef(new AccessibilityMediaTimeDisplay(renderer));
301 }
302
303 bool AccessibilityMediaTimeDisplay::computeAccessibilityIsIgnored() const
304 {
305     if (!m_renderer || !m_renderer->style() || m_renderer->style()->visibility() != VISIBLE)
306         return true;
307
308     return !m_renderer->style()->width().value();
309 }
310
311 String AccessibilityMediaTimeDisplay::accessibilityDescription() const
312 {
313     DEFINE_STATIC_LOCAL(const String, currentTimeDisplay, (ASCIILiteral("CurrentTimeDisplay")));
314     DEFINE_STATIC_LOCAL(const String, timeRemainingDisplay, (ASCIILiteral("TimeRemainingDisplay")));
315
316     if (controlType() == MediaCurrentTimeDisplay)
317         return localizedMediaControlElementString(currentTimeDisplay);
318
319     return localizedMediaControlElementString(timeRemainingDisplay);
320 }
321
322 String AccessibilityMediaTimeDisplay::stringValue() const
323 {
324     if (!m_renderer || !m_renderer->node())
325         return String();
326
327     MediaControlTimeDisplayElement* element = static_cast<MediaControlTimeDisplayElement*>(m_renderer->node());
328     float time = element->currentValue();
329     return localizedMediaTimeDescription(fabsf(time));
330 }
331
332 } // namespace WebCore
333
334 #endif // ENABLE(VIDEO)