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 45namespace WebCore { 46 47using namespace HTMLNames; 48 49 50AccessibilityMediaControl::AccessibilityMediaControl(RenderObject* renderer) 51 : AccessibilityRenderObject(renderer) 52{ 53} 54 55PassRefPtr<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 75MediaControlElementType 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 83String 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 140void 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 156String 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 166String AccessibilityMediaControl::accessibilityDescription() const 167{ 168 return localizedMediaControlElementString(controlTypeName()); 169} 170 171String AccessibilityMediaControl::helpText() const 172{ 173 return localizedMediaControlElementHelpText(controlTypeName()); 174} 175 176bool 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 184AccessibilityRole 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 219AccessibilityMediaControlsContainer::AccessibilityMediaControlsContainer(RenderObject* renderer) 220 : AccessibilityMediaControl(renderer) 221{ 222} 223 224PassRefPtr<AccessibilityObject> AccessibilityMediaControlsContainer::create(RenderObject* renderer) 225{ 226 return adoptRef(new AccessibilityMediaControlsContainer(renderer)); 227} 228 229String AccessibilityMediaControlsContainer::accessibilityDescription() const 230{ 231 return localizedMediaControlElementString(elementTypeName()); 232} 233 234String AccessibilityMediaControlsContainer::helpText() const 235{ 236 return localizedMediaControlElementHelpText(elementTypeName()); 237} 238 239bool 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 249const 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 259bool AccessibilityMediaControlsContainer::computeAccessibilityIsIgnored() const 260{ 261 return accessibilityIsIgnoredByDefault(); 262} 263 264// 265// AccessibilityMediaTimeline 266 267AccessibilityMediaTimeline::AccessibilityMediaTimeline(RenderObject* renderer) 268 : AccessibilitySlider(renderer) 269{ 270} 271 272PassRefPtr<AccessibilityObject> AccessibilityMediaTimeline::create(RenderObject* renderer) 273{ 274 return adoptRef(new AccessibilityMediaTimeline(renderer)); 275} 276 277String 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 287String AccessibilityMediaTimeline::helpText() const 288{ 289 DEFINE_STATIC_LOCAL(const String, slider, (ASCIILiteral("Slider"))); 290 return localizedMediaControlElementHelpText(slider); 291} 292 293 294// 295// AccessibilityMediaTimeDisplay 296 297AccessibilityMediaTimeDisplay::AccessibilityMediaTimeDisplay(RenderObject* renderer) 298 : AccessibilityMediaControl(renderer) 299{ 300} 301 302PassRefPtr<AccessibilityObject> AccessibilityMediaTimeDisplay::create(RenderObject* renderer) 303{ 304 return adoptRef(new AccessibilityMediaTimeDisplay(renderer)); 305} 306 307bool 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 318String 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 329String 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) 342