Source/WebCore:
[WebKit-https.git] / Source / WebCore / accessibility / AccessibilityMediaObject.cpp
1 /*
2  * Copyright (C) 2017 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 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 #include "config.h"
30
31 #if PLATFORM(IOS_FAMILY)
32 #include "AccessibilityMediaObject.h"
33
34 #include "HTMLMediaElement.h"
35 #include "HTMLNames.h"
36 #include "HTMLVideoElement.h"
37 #include "LocalizedStrings.h"
38
39
40 namespace WebCore {
41     
42 using namespace HTMLNames;
43
44 AccessibilityMediaObject::AccessibilityMediaObject(RenderObject* renderer)
45     : AccessibilityRenderObject(renderer)
46 {
47 }
48
49 AccessibilityMediaObject::~AccessibilityMediaObject() = default;
50
51 Ref<AccessibilityMediaObject> AccessibilityMediaObject::create(RenderObject* renderer)
52 {
53     return adoptRef(*new AccessibilityMediaObject(renderer));
54 }
55
56 bool AccessibilityMediaObject::computeAccessibilityIsIgnored() const
57 {
58     return accessibilityIsIgnoredByDefault();
59 }
60
61 HTMLMediaElement* AccessibilityMediaObject::mediaElement() const
62 {
63     Node* node = this->node();
64     if (!is<HTMLMediaElement>(*node))
65         return nullptr;
66     return downcast<HTMLMediaElement>(node);
67 }
68
69 String AccessibilityMediaObject::stringValue() const
70 {
71     if (HTMLMediaElement* element = mediaElement())
72         return localizedMediaTimeDescription(element->currentTime());
73     return AccessibilityRenderObject::stringValue();
74 }
75
76 String AccessibilityMediaObject::interactiveVideoDuration() const
77 {
78     if (HTMLMediaElement* element = mediaElement())
79         return localizedMediaTimeDescription(element->duration());
80     return String();
81 }
82     
83 void AccessibilityMediaObject::mediaSeek(AXSeekDirection direction)
84 {
85     HTMLMediaElement* element = mediaElement();
86     if (!element)
87         return;
88     
89     // Step 5% each time.
90     const double seekStep = .05;
91     double current = element->currentTime();
92     double duration = element->duration();
93     double timeDelta = ceil(duration * seekStep);
94
95     double time = direction == AXSeekForward ? std::min(current + timeDelta, duration) : std::max(current - timeDelta, 0.0);
96     element->setCurrentTime(time);
97 }
98
99 void AccessibilityMediaObject::toggleMute()
100 {
101     HTMLMediaElement* element = mediaElement();
102     if (!element)
103         return;
104     
105     element->setMuted(!element->muted());
106 }
107
108 void AccessibilityMediaObject::increment()
109 {
110     if (dispatchAccessibilityEventWithType(AccessibilityEventType::Increment))
111         return;
112     mediaSeek(AXSeekForward);
113 }
114
115 void AccessibilityMediaObject::decrement()
116 {
117     if (dispatchAccessibilityEventWithType(AccessibilityEventType::Decrement))
118         return;
119     mediaSeek(AXSeekBackward);
120 }
121
122 bool AccessibilityMediaObject::press()
123 {
124     HTMLMediaElement* element = mediaElement();
125     if (!element)
126         return false;
127     
128     // We can safely call the internal togglePlayState method, which doesn't check restrictions,
129     // because this method is only called from user interaction.
130     element->togglePlayState();
131     return true;
132 }
133
134 bool AccessibilityMediaObject::hasControlsAttributeSet() const
135 {
136     HTMLMediaElement* element = mediaElement();
137     if (!element)
138         return false;
139     
140     return element->controls();
141 }
142     
143 bool AccessibilityMediaObject::isPlaying() const
144 {
145     HTMLMediaElement* element = mediaElement();
146     if (!element)
147         return false;
148     
149     return element->isPlaying();
150 }
151
152 bool AccessibilityMediaObject::isMuted() const
153 {
154     HTMLMediaElement* element = mediaElement();
155     if (!element)
156         return false;
157     
158     return element->muted();
159 }
160
161 bool AccessibilityMediaObject::isAutoplayEnabled() const
162 {
163     HTMLMediaElement* element = mediaElement();
164     if (!element)
165         return false;
166     
167     return element->autoplay();
168 }
169
170 bool AccessibilityMediaObject::isPlayingInline() const
171 {
172     HTMLMediaElement* element = mediaElement();
173     if (!element)
174         return false;
175     
176     return !element->mediaSession().requiresFullscreenForVideoPlayback();
177 }
178
179 void AccessibilityMediaObject::enterFullscreen() const
180 {
181     Node* node = this->node();
182     if (!is<HTMLVideoElement>(node))
183         return;
184     
185     HTMLVideoElement* element = downcast<HTMLVideoElement>(node);
186     element->enterFullscreen();
187 }
188     
189 } // namespace WebCore
190
191 #endif // PLATFORM(IOS_FAMILY)