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#include "core/accessibility/AccessibilityMediaControls.h"
33
34#include "core/platform/LocalizedStrings.h"
35
36namespace WebCore {
37
38using namespace HTMLNames;
39
40
41AccessibilityMediaControl::AccessibilityMediaControl(RenderObject* renderer)
42    : AccessibilityRenderObject(renderer)
43{
44}
45
46PassRefPtr<AccessibilityObject> AccessibilityMediaControl::create(RenderObject* renderer)
47{
48    ASSERT(renderer->node());
49
50    switch (mediaControlElementType(renderer->node())) {
51    case MediaSlider:
52        return AccessibilityMediaTimeline::create(renderer);
53
54    case MediaCurrentTimeDisplay:
55    case MediaTimeRemainingDisplay:
56        return AccessibilityMediaTimeDisplay::create(renderer);
57
58    case MediaControlsPanel:
59        return AccessibilityMediaControlsContainer::create(renderer);
60
61    default:
62        return adoptRef(new AccessibilityMediaControl(renderer));
63    }
64}
65
66MediaControlElementType AccessibilityMediaControl::controlType() const
67{
68    if (!renderer() || !renderer()->node())
69        return MediaTimelineContainer; // Timeline container is not accessible.
70
71    return mediaControlElementType(renderer()->node());
72}
73
74String AccessibilityMediaControl::controlTypeName() const
75{
76    switch (controlType()) {
77    case MediaEnterFullscreenButton:
78        return "EnterFullscreenButton";
79    case MediaExitFullscreenButton:
80        return "ExitFullscreenButton";
81    case MediaMuteButton:
82        return "MuteButton";
83    case MediaPlayButton:
84        return "PlayButton";
85    case MediaSeekBackButton:
86        return "SeekBackButton";
87    case MediaSeekForwardButton:
88        return "SeekForwardButton";
89    case MediaRewindButton:
90        return "RewindButton";
91    case MediaReturnToRealtimeButton:
92        return "ReturnToRealtimeButton";
93    case MediaUnMuteButton:
94        return "UnMuteButton";
95    case MediaPauseButton:
96        return "PauseButton";
97    case MediaStatusDisplay:
98        return "StatusDisplay";
99    case MediaCurrentTimeDisplay:
100        return "CurrentTimeDisplay";
101    case MediaTimeRemainingDisplay:
102        return "TimeRemainingDisplay";
103    case MediaShowClosedCaptionsButton:
104        return "ShowClosedCaptionsButton";
105    case MediaHideClosedCaptionsButton:
106        return "HideClosedCaptionsButton";
107
108    default:
109        break;
110    }
111
112    return String();
113}
114
115void AccessibilityMediaControl::accessibilityText(Vector<AccessibilityText>& textOrder)
116{
117    String description = accessibilityDescription();
118    if (!description.isEmpty())
119        textOrder.append(AccessibilityText(description, AlternativeText));
120
121    String title = this->title();
122    if (!title.isEmpty())
123        textOrder.append(AccessibilityText(title, AlternativeText));
124
125    String helptext = helpText();
126    if (!helptext.isEmpty())
127        textOrder.append(AccessibilityText(helptext, HelpText));
128}
129
130
131String AccessibilityMediaControl::title() const
132{
133    if (controlType() == MediaControlsPanel)
134        return localizedMediaControlElementString("ControlsPanel");
135
136    return AccessibilityRenderObject::title();
137}
138
139String AccessibilityMediaControl::accessibilityDescription() const
140{
141    return localizedMediaControlElementString(controlTypeName());
142}
143
144String AccessibilityMediaControl::helpText() const
145{
146    return localizedMediaControlElementHelpText(controlTypeName());
147}
148
149bool AccessibilityMediaControl::computeAccessibilityIsIgnored() const
150{
151    if (!m_renderer || !m_renderer->style() || m_renderer->style()->visibility() != VISIBLE || controlType() == MediaTimelineContainer)
152        return true;
153
154    return accessibilityIsIgnoredByDefault();
155}
156
157AccessibilityRole AccessibilityMediaControl::roleValue() const
158{
159    switch (controlType()) {
160    case MediaEnterFullscreenButton:
161    case MediaExitFullscreenButton:
162    case MediaMuteButton:
163    case MediaPlayButton:
164    case MediaSeekBackButton:
165    case MediaSeekForwardButton:
166    case MediaRewindButton:
167    case MediaReturnToRealtimeButton:
168    case MediaUnMuteButton:
169    case MediaPauseButton:
170    case MediaShowClosedCaptionsButton:
171    case MediaHideClosedCaptionsButton:
172        return ButtonRole;
173
174    case MediaStatusDisplay:
175        return StaticTextRole;
176
177    case MediaTimelineContainer:
178        return GroupRole;
179
180    default:
181        break;
182    }
183
184    return UnknownRole;
185}
186
187
188
189//
190// AccessibilityMediaControlsContainer
191
192AccessibilityMediaControlsContainer::AccessibilityMediaControlsContainer(RenderObject* renderer)
193    : AccessibilityMediaControl(renderer)
194{
195}
196
197PassRefPtr<AccessibilityObject> AccessibilityMediaControlsContainer::create(RenderObject* renderer)
198{
199    return adoptRef(new AccessibilityMediaControlsContainer(renderer));
200}
201
202String AccessibilityMediaControlsContainer::accessibilityDescription() const
203{
204    return localizedMediaControlElementString(elementTypeName());
205}
206
207String AccessibilityMediaControlsContainer::helpText() const
208{
209    return localizedMediaControlElementHelpText(elementTypeName());
210}
211
212bool AccessibilityMediaControlsContainer::controllingVideoElement() const
213{
214    if (!m_renderer->node())
215        return true;
216
217    MediaControlTimeDisplayElement* element = static_cast<MediaControlTimeDisplayElement*>(m_renderer->node());
218
219    return toParentMediaElement(element)->isVideo();
220}
221
222const String AccessibilityMediaControlsContainer::elementTypeName() const
223{
224    if (controllingVideoElement())
225        return "VideoElement";
226    return "AudioElement";
227}
228
229bool AccessibilityMediaControlsContainer::computeAccessibilityIsIgnored() const
230{
231    return accessibilityIsIgnoredByDefault();
232}
233
234//
235// AccessibilityMediaTimeline
236
237AccessibilityMediaTimeline::AccessibilityMediaTimeline(RenderObject* renderer)
238    : AccessibilitySlider(renderer)
239{
240}
241
242PassRefPtr<AccessibilityObject> AccessibilityMediaTimeline::create(RenderObject* renderer)
243{
244    return adoptRef(new AccessibilityMediaTimeline(renderer));
245}
246
247String AccessibilityMediaTimeline::valueDescription() const
248{
249    Node* node = m_renderer->node();
250    if (!node->hasTagName(inputTag))
251        return String();
252
253    return localizedMediaTimeDescription(toHTMLInputElement(node)->value().toFloat());
254}
255
256String AccessibilityMediaTimeline::helpText() const
257{
258    return localizedMediaControlElementHelpText("Slider");
259}
260
261
262//
263// AccessibilityMediaTimeDisplay
264
265AccessibilityMediaTimeDisplay::AccessibilityMediaTimeDisplay(RenderObject* renderer)
266    : AccessibilityMediaControl(renderer)
267{
268}
269
270PassRefPtr<AccessibilityObject> AccessibilityMediaTimeDisplay::create(RenderObject* renderer)
271{
272    return adoptRef(new AccessibilityMediaTimeDisplay(renderer));
273}
274
275bool AccessibilityMediaTimeDisplay::computeAccessibilityIsIgnored() const
276{
277    if (!m_renderer || !m_renderer->style() || m_renderer->style()->visibility() != VISIBLE)
278        return true;
279
280    if (!m_renderer->style()->width().value())
281        return true;
282
283    return accessibilityIsIgnoredByDefault();
284}
285
286String AccessibilityMediaTimeDisplay::accessibilityDescription() const
287{
288    if (controlType() == MediaCurrentTimeDisplay)
289        return localizedMediaControlElementString("CurrentTimeDisplay");
290
291    return localizedMediaControlElementString("TimeRemainingDisplay");
292}
293
294String AccessibilityMediaTimeDisplay::stringValue() const
295{
296    if (!m_renderer || !m_renderer->node())
297        return String();
298
299    MediaControlTimeDisplayElement* element = static_cast<MediaControlTimeDisplayElement*>(m_renderer->node());
300    float time = element->currentValue();
301    return localizedMediaTimeDescription(fabsf(time));
302}
303
304} // namespace WebCore
305