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 "HTMLNames.h"
39#include "LocalizedStrings.h"
40#include "MediaControlElements.h"
41#include "RenderObject.h"
42#include "RenderSlider.h"
43
44namespace WebCore {
45
46using namespace HTMLNames;
47
48
49AccessibilityMediaControl::AccessibilityMediaControl(RenderObject* renderer)
50    : AccessibilityRenderObject(renderer)
51{
52}
53
54PassRefPtr<AccessibilityObject> AccessibilityMediaControl::create(RenderObject* renderer)
55{
56    ASSERT(renderer->node() && renderer->node()->isMediaControlElement());
57
58    Node* node = renderer->node();
59    MediaControlElementType controlType;
60
61    if (node->hasTagName(inputTag))
62        controlType = static_cast<MediaControlInputElement*>(node)->displayType();
63    else
64        controlType = static_cast<MediaControlElement*>(node)->displayType();
65
66    PassRefPtr<AccessibilityObject> obj;
67    switch (controlType) {
68    case MediaSlider:
69        obj = AccessibilityMediaTimeline::create(renderer);
70        break;
71
72    case MediaCurrentTimeDisplay:
73    case MediaTimeRemainingDisplay:
74        obj = AccessibilityMediaTimeDisplay::create(renderer);
75        break;
76
77    case MediaControlsPanel:
78        obj = AccessibilityMediaControlsContainer::create(renderer);
79        break;
80
81    default:
82        obj = adoptRef(new AccessibilityMediaControl(renderer));
83        break;
84    }
85
86    return obj;
87}
88
89MediaControlElementType AccessibilityMediaControl::controlType() const
90{
91    if (!renderer() || !renderer()->node())
92        return MediaTimelineContainer; // Timeline container is not accessible.
93
94    Node* node = renderer()->node();
95
96    if (node->hasTagName(inputTag))
97        return static_cast<MediaControlInputElement*>(node)->displayType();
98
99    return static_cast<MediaControlElement*>(node)->displayType();
100}
101
102String AccessibilityMediaControl::controlTypeName() const
103{
104    DEFINE_STATIC_LOCAL(const String, mediaFullscreenButtonName, ("FullscreenButton"));
105    DEFINE_STATIC_LOCAL(const String, mediaMuteButtonName, ("MuteButton"));
106    DEFINE_STATIC_LOCAL(const String, mediaPlayButtonName, ("PlayButton"));
107    DEFINE_STATIC_LOCAL(const String, mediaSeekBackButtonName, ("SeekBackButton"));
108    DEFINE_STATIC_LOCAL(const String, mediaSeekForwardButtonName, ("SeekForwardButton"));
109    DEFINE_STATIC_LOCAL(const String, mediaRewindButtonName, ("RewindButton"));
110    DEFINE_STATIC_LOCAL(const String, mediaReturnToRealtimeButtonName, ("ReturnToRealtimeButton"));
111    DEFINE_STATIC_LOCAL(const String, mediaUnMuteButtonName, ("UnMuteButton"));
112    DEFINE_STATIC_LOCAL(const String, mediaPauseButtonName, ("PauseButton"));
113    DEFINE_STATIC_LOCAL(const String, mediaStatusDisplayName, ("StatusDisplay"));
114    DEFINE_STATIC_LOCAL(const String, mediaCurrentTimeDisplay, ("CurrentTimeDisplay"));
115    DEFINE_STATIC_LOCAL(const String, mediaTimeRemainingDisplay, ("TimeRemainingDisplay"));
116    DEFINE_STATIC_LOCAL(const String, mediaShowClosedCaptionsButtonName, ("ShowClosedCaptionsButton"));
117    DEFINE_STATIC_LOCAL(const String, mediaHideClosedCaptionsButtonName, ("HideClosedCaptionsButton"));
118
119    switch (controlType()) {
120    case MediaFullscreenButton:
121        return mediaFullscreenButtonName;
122    case MediaMuteButton:
123        return mediaMuteButtonName;
124    case MediaPlayButton:
125        return mediaPlayButtonName;
126    case MediaSeekBackButton:
127        return mediaSeekBackButtonName;
128    case MediaSeekForwardButton:
129        return mediaSeekForwardButtonName;
130    case MediaRewindButton:
131        return mediaRewindButtonName;
132    case MediaReturnToRealtimeButton:
133        return mediaReturnToRealtimeButtonName;
134    case MediaUnMuteButton:
135        return mediaUnMuteButtonName;
136    case MediaPauseButton:
137        return mediaPauseButtonName;
138    case MediaStatusDisplay:
139        return mediaStatusDisplayName;
140    case MediaCurrentTimeDisplay:
141        return mediaCurrentTimeDisplay;
142    case MediaTimeRemainingDisplay:
143        return mediaTimeRemainingDisplay;
144    case MediaShowClosedCaptionsButton:
145        return mediaShowClosedCaptionsButtonName;
146    case MediaHideClosedCaptionsButton:
147        return mediaHideClosedCaptionsButtonName;
148
149    default:
150        break;
151    }
152
153    return String();
154}
155
156String AccessibilityMediaControl::title() const
157{
158    DEFINE_STATIC_LOCAL(const String, controlsPanel, ("ControlsPanel"));
159
160    if (controlType() == MediaControlsPanel)
161        return localizedMediaControlElementString(controlsPanel);
162
163    return AccessibilityRenderObject::title();
164}
165
166String AccessibilityMediaControl::accessibilityDescription() const
167{
168    return localizedMediaControlElementString(controlTypeName());
169}
170
171String AccessibilityMediaControl::helpText() const
172{
173    return localizedMediaControlElementHelpText(controlTypeName());
174}
175
176bool AccessibilityMediaControl::accessibilityIsIgnored() 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
184AccessibilityRole AccessibilityMediaControl::roleValue() const
185{
186    switch (controlType()) {
187    case MediaFullscreenButton:
188    case MediaMuteButton:
189    case MediaPlayButton:
190    case MediaSeekBackButton:
191    case MediaSeekForwardButton:
192    case MediaRewindButton:
193    case MediaReturnToRealtimeButton:
194    case MediaUnMuteButton:
195    case MediaPauseButton:
196    case MediaShowClosedCaptionsButton:
197    case MediaHideClosedCaptionsButton:
198        return ButtonRole;
199
200    case MediaStatusDisplay:
201        return StaticTextRole;
202
203    case MediaTimelineContainer:
204        return GroupRole;
205
206    default:
207        break;
208    }
209
210    return UnknownRole;
211}
212
213
214
215//
216// AccessibilityMediaControlsContainer
217
218AccessibilityMediaControlsContainer::AccessibilityMediaControlsContainer(RenderObject* renderer)
219    : AccessibilityMediaControl(renderer)
220{
221}
222
223PassRefPtr<AccessibilityObject> AccessibilityMediaControlsContainer::create(RenderObject* renderer)
224{
225    return adoptRef(new AccessibilityMediaControlsContainer(renderer));
226}
227
228String AccessibilityMediaControlsContainer::accessibilityDescription() const
229{
230    return localizedMediaControlElementString(elementTypeName());
231}
232
233String AccessibilityMediaControlsContainer::helpText() const
234{
235    return localizedMediaControlElementHelpText(elementTypeName());
236}
237
238bool AccessibilityMediaControlsContainer::controllingVideoElement() const
239{
240    if (!m_renderer->node())
241        return true;
242
243    MediaControlTimeDisplayElement* element = static_cast<MediaControlTimeDisplayElement*>(m_renderer->node());
244
245    return element->mediaElement()->isVideo();
246}
247
248const String AccessibilityMediaControlsContainer::elementTypeName() const
249{
250    DEFINE_STATIC_LOCAL(const String, videoElement, ("VideoElement"));
251    DEFINE_STATIC_LOCAL(const String, audioElement, ("AudioElement"));
252
253    if (controllingVideoElement())
254        return videoElement;
255    return audioElement;
256}
257
258
259//
260// AccessibilityMediaTimeline
261
262AccessibilityMediaTimeline::AccessibilityMediaTimeline(RenderObject* renderer)
263    : AccessibilitySlider(renderer)
264{
265}
266
267PassRefPtr<AccessibilityObject> AccessibilityMediaTimeline::create(RenderObject* renderer)
268{
269    return adoptRef(new AccessibilityMediaTimeline(renderer));
270}
271
272String AccessibilityMediaTimeline::valueDescription() const
273{
274    ASSERT(m_renderer->node()->hasTagName(inputTag));
275
276    float time = static_cast<HTMLInputElement*>(m_renderer->node())->value().toFloat();
277    return localizedMediaTimeDescription(time);
278}
279
280String AccessibilityMediaTimeline::helpText() const
281{
282    DEFINE_STATIC_LOCAL(const String, slider, ("Slider"));
283    return localizedMediaControlElementHelpText(slider);
284}
285
286
287//
288// AccessibilityMediaTimeDisplay
289
290AccessibilityMediaTimeDisplay::AccessibilityMediaTimeDisplay(RenderObject* renderer)
291    : AccessibilityMediaControl(renderer)
292{
293}
294
295PassRefPtr<AccessibilityObject> AccessibilityMediaTimeDisplay::create(RenderObject* renderer)
296{
297    return adoptRef(new AccessibilityMediaTimeDisplay(renderer));
298}
299
300bool AccessibilityMediaTimeDisplay::accessibilityIsIgnored() const
301{
302    if (!m_renderer || !m_renderer->style() || m_renderer->style()->visibility() != VISIBLE)
303        return true;
304
305    return !m_renderer->style()->width().value();
306}
307
308String AccessibilityMediaTimeDisplay::accessibilityDescription() const
309{
310    DEFINE_STATIC_LOCAL(const String, currentTimeDisplay, ("CurrentTimeDisplay"));
311    DEFINE_STATIC_LOCAL(const String, timeRemainingDisplay, ("TimeRemainingDisplay"));
312
313    if (controlType() == MediaCurrentTimeDisplay)
314        return localizedMediaControlElementString(currentTimeDisplay);
315
316    return localizedMediaControlElementString(timeRemainingDisplay);
317}
318
319String AccessibilityMediaTimeDisplay::stringValue() const
320{
321    if (!m_renderer || !m_renderer->node())
322        return String();
323
324    MediaControlTimeDisplayElement* element = static_cast<MediaControlTimeDisplayElement*>(m_renderer->node());
325    float time = element->currentValue();
326    return localizedMediaTimeDescription(fabsf(time));
327}
328
329} // namespace WebCore
330
331#endif // ENABLE(VIDEO)
332