1/*
2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Google Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
15 *     its contributors may be used to endorse or promote products derived
16 *     from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "config.h"
31
32#if ENABLE(VIDEO)
33#include "MediaControlElementTypes.h"
34
35#include "CSSValueKeywords.h"
36#include "ExceptionCodePlaceholder.h"
37#include "HTMLNames.h"
38#include "MouseEvent.h"
39#include "RenderMedia.h"
40#include "RenderMediaControlElements.h"
41#include "StyleProperties.h"
42
43namespace WebCore {
44
45using namespace HTMLNames;
46
47class Event;
48
49HTMLMediaElement* parentMediaElement(Node* node)
50{
51    if (!node)
52        return nullptr;
53    Node* mediaNode = node->shadowHost();
54    if (!mediaNode)
55        mediaNode = node;
56    if (!mediaNode->isElementNode() || !toElement(mediaNode)->isMediaElement())
57        return nullptr;
58    return toHTMLMediaElement(mediaNode);
59}
60
61MediaControlElementType mediaControlElementType(Node* node)
62{
63    ASSERT_WITH_SECURITY_IMPLICATION(node->isMediaControlElement());
64    HTMLElement* element = toHTMLElement(node);
65    if (isHTMLInputElement(element))
66        return static_cast<MediaControlInputElement*>(element)->displayType();
67    return static_cast<MediaControlDivElement*>(element)->displayType();
68}
69
70MediaControlElement::MediaControlElement(MediaControlElementType displayType, HTMLElement* element)
71    : m_mediaController(0)
72    , m_displayType(displayType)
73    , m_element(element)
74{
75}
76
77void MediaControlElement::hide()
78{
79    m_element->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
80}
81
82void MediaControlElement::show()
83{
84    m_element->removeInlineStyleProperty(CSSPropertyDisplay);
85}
86
87bool MediaControlElement::isShowing() const
88{
89    const StyleProperties* propertySet = m_element->inlineStyle();
90    // Following the code from show() and hide() above, we only have
91    // to check for the presense of inline display.
92    return (!propertySet || !propertySet->getPropertyCSSValue(CSSPropertyDisplay));
93}
94
95void MediaControlElement::setDisplayType(MediaControlElementType displayType)
96{
97    if (displayType == m_displayType)
98        return;
99
100    m_displayType = displayType;
101    if (auto object = m_element->renderer())
102        object->repaint();
103}
104
105// ----------------------------
106
107MediaControlDivElement::MediaControlDivElement(Document& document, MediaControlElementType displayType)
108    : HTMLDivElement(divTag, document)
109    , MediaControlElement(displayType, this)
110{
111}
112
113// ----------------------------
114
115MediaControlInputElement::MediaControlInputElement(Document& document, MediaControlElementType displayType)
116    : HTMLInputElement(inputTag, document, 0, false)
117    , MediaControlElement(displayType, this)
118{
119}
120
121// ----------------------------
122
123MediaControlTimeDisplayElement::MediaControlTimeDisplayElement(Document& document, MediaControlElementType displayType)
124    : MediaControlDivElement(document, displayType)
125    , m_currentValue(0)
126{
127}
128
129void MediaControlTimeDisplayElement::setCurrentValue(double time)
130{
131    m_currentValue = time;
132}
133
134// ----------------------------
135
136MediaControlMuteButtonElement::MediaControlMuteButtonElement(Document& document, MediaControlElementType displayType)
137    : MediaControlInputElement(document, displayType)
138{
139}
140
141void MediaControlMuteButtonElement::defaultEventHandler(Event* event)
142{
143    if (event->type() == eventNames().clickEvent) {
144        mediaController()->setMuted(!mediaController()->muted());
145        event->setDefaultHandled();
146    }
147
148    HTMLInputElement::defaultEventHandler(event);
149}
150
151void MediaControlMuteButtonElement::changedMute()
152{
153    updateDisplayType();
154}
155
156void MediaControlMuteButtonElement::updateDisplayType()
157{
158    setDisplayType(mediaController()->muted() ? MediaUnMuteButton : MediaMuteButton);
159}
160
161// ----------------------------
162
163MediaControlSeekButtonElement::MediaControlSeekButtonElement(Document& document, MediaControlElementType displayType)
164    : MediaControlInputElement(document, displayType)
165{
166}
167
168void MediaControlSeekButtonElement::defaultEventHandler(Event* event)
169{
170    // Set the mousedown and mouseup events as defaultHandled so they
171    // do not trigger drag start or end actions in MediaControlPanelElement.
172    if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent)
173        event->setDefaultHandled();
174}
175
176void MediaControlSeekButtonElement::setActive(bool flag, bool pause)
177{
178    if (flag == active())
179        return;
180
181    if (flag)
182        mediaController()->beginScanning(isForwardButton() ? MediaControllerInterface::Forward : MediaControllerInterface::Backward);
183    else
184        mediaController()->endScanning();
185
186    MediaControlInputElement::setActive(flag, pause);
187}
188
189// ----------------------------
190
191MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(Document& document)
192    : MediaControlInputElement(document, MediaVolumeSlider)
193    , m_clearMutedOnUserInteraction(false)
194{
195}
196
197void MediaControlVolumeSliderElement::defaultEventHandler(Event* event)
198{
199    // Left button is 0. Rejects mouse events not from left button.
200    if (event->isMouseEvent() && toMouseEvent(event)->button())
201        return;
202
203    if (!renderer())
204        return;
205
206    MediaControlInputElement::defaultEventHandler(event);
207
208    if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
209        return;
210
211    double volume = value().toDouble();
212    if (volume != mediaController()->volume())
213        mediaController()->setVolume(volume, ASSERT_NO_EXCEPTION);
214    if (m_clearMutedOnUserInteraction)
215        mediaController()->setMuted(false);
216    event->setDefaultHandled();
217}
218
219bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents()
220{
221    if (!renderer())
222        return false;
223
224    return MediaControlInputElement::willRespondToMouseMoveEvents();
225}
226
227bool MediaControlVolumeSliderElement::willRespondToMouseClickEvents()
228{
229    if (!renderer())
230        return false;
231
232    return MediaControlInputElement::willRespondToMouseClickEvents();
233}
234
235void MediaControlVolumeSliderElement::setVolume(double volume)
236{
237    if (value().toDouble() != volume)
238        setValue(String::number(volume));
239}
240
241void MediaControlVolumeSliderElement::setClearMutedOnUserInteraction(bool clearMute)
242{
243    m_clearMutedOnUserInteraction = clearMute;
244}
245
246} // namespace WebCore
247
248#endif // ENABLE(VIDEO)
249