blob: af2f891bd1e168de9b0f5d1428d01ec8b1572a88 [file] [log] [blame]
/*
* Copyright (C) 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2011 Google Inc. All rights reserved.
* Copyright (C) 2012 Research In Motion Limited. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#if ENABLE(VIDEO)
#include "MediaControlsBlackBerry.h"
#include "DOMTokenList.h"
#include "ExceptionCodePlaceholder.h"
#include "Frame.h"
#include "HTMLNames.h"
#include "RenderDeprecatedFlexibleBox.h"
#include "RenderSlider.h"
#include "Settings.h"
using namespace std;
namespace WebCore {
using namespace HTMLNames;
static const double timeWithoutMouseMovementBeforeHidingControls = 3;
inline MediaControlButtonGroupContainerElement::MediaControlButtonGroupContainerElement(Document* document)
: MediaControlDivElement(document, MediaControlsPanel)
{
}
PassRefPtr<MediaControlButtonGroupContainerElement> MediaControlButtonGroupContainerElement::create(Document* document)
{
RefPtr<MediaControlButtonGroupContainerElement> element = adoptRef(new MediaControlButtonGroupContainerElement(document));
return element.release();
}
const AtomicString& MediaControlButtonGroupContainerElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-button-group-container", AtomicString::ConstructFromLiteral));
return id;
}
inline MediaControlTimeDisplayContainerElement::MediaControlTimeDisplayContainerElement(Document* document)
: MediaControlDivElement(document, MediaControlsPanel)
{
}
PassRefPtr<MediaControlTimeDisplayContainerElement> MediaControlTimeDisplayContainerElement::create(Document* document)
{
RefPtr<MediaControlTimeDisplayContainerElement> element = adoptRef(new MediaControlTimeDisplayContainerElement(document));
return element.release();
}
const AtomicString& MediaControlTimeDisplayContainerElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-time-display-container", AtomicString::ConstructFromLiteral));
return id;
}
MediaControlEmbeddedPanelElement::MediaControlEmbeddedPanelElement(Document* document)
: MediaControlDivElement(document, MediaControlsPanel)
, m_canBeDragged(false)
, m_isBeingDragged(false)
, m_isDisplayed(false)
, m_opaque(true)
, m_transitionTimer(this, &MediaControlEmbeddedPanelElement::transitionTimerFired)
{
}
PassRefPtr<MediaControlEmbeddedPanelElement> MediaControlEmbeddedPanelElement::create(Document* document)
{
return adoptRef(new MediaControlEmbeddedPanelElement(document));
}
const AtomicString& MediaControlEmbeddedPanelElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-embedded-panel", AtomicString::ConstructFromLiteral));
return id;
}
void MediaControlEmbeddedPanelElement::startDrag(const LayoutPoint& eventLocation)
{
if (!m_canBeDragged)
return;
if (m_isBeingDragged)
return;
RenderObject* renderer = this->renderer();
if (!renderer || !renderer->isBox())
return;
Frame* frame = document()->frame();
if (!frame)
return;
m_lastDragEventLocation = eventLocation;
frame->eventHandler().setCapturingMouseEventsNode(this);
m_isBeingDragged = true;
}
void MediaControlEmbeddedPanelElement::continueDrag(const LayoutPoint& eventLocation)
{
if (!m_isBeingDragged)
return;
LayoutSize distanceDragged = eventLocation - m_lastDragEventLocation;
m_cumulativeDragOffset.move(distanceDragged);
m_lastDragEventLocation = eventLocation;
setPosition(m_cumulativeDragOffset);
}
void MediaControlEmbeddedPanelElement::endDrag()
{
if (!m_isBeingDragged)
return;
m_isBeingDragged = false;
Frame* frame = document()->frame();
if (!frame)
return;
frame->eventHandler().setCapturingMouseEventsNode(0);
}
void MediaControlEmbeddedPanelElement::startTimer()
{
stopTimer();
// The timer is required to set the property display:'none' on the panel,
// such that captions are correctly displayed at the bottom of the video
// at the end of the fadeout transition.
double duration = document()->page() ? document()->page()->theme()->mediaControlsFadeOutDuration() : 0;
m_transitionTimer.startOneShot(duration);
}
void MediaControlEmbeddedPanelElement::stopTimer()
{
if (m_transitionTimer.isActive())
m_transitionTimer.stop();
}
void MediaControlEmbeddedPanelElement::transitionTimerFired(Timer<MediaControlEmbeddedPanelElement>*)
{
if (!m_opaque)
hide();
stopTimer();
}
void MediaControlEmbeddedPanelElement::setPosition(const LayoutPoint& position)
{
double left = position.x();
double top = position.y();
// Set the left and top to control the panel's position; this depends on it being absolute positioned.
// Set the margin to zero since the position passed in will already include the effect of the margin.
setInlineStyleProperty(CSSPropertyLeft, left, CSSPrimitiveValue::CSS_PX);
setInlineStyleProperty(CSSPropertyTop, top, CSSPrimitiveValue::CSS_PX);
setInlineStyleProperty(CSSPropertyMarginLeft, 0.0, CSSPrimitiveValue::CSS_PX);
setInlineStyleProperty(CSSPropertyMarginTop, 0.0, CSSPrimitiveValue::CSS_PX);
classList()->add("dragged", IGNORE_EXCEPTION);
}
void MediaControlEmbeddedPanelElement::resetPosition()
{
removeInlineStyleProperty(CSSPropertyLeft);
removeInlineStyleProperty(CSSPropertyTop);
removeInlineStyleProperty(CSSPropertyMarginLeft);
removeInlineStyleProperty(CSSPropertyMarginTop);
classList()->remove("dragged", IGNORE_EXCEPTION);
m_cumulativeDragOffset.setX(0);
m_cumulativeDragOffset.setY(0);
}
void MediaControlEmbeddedPanelElement::makeOpaque()
{
if (m_opaque)
return;
double duration = document()->page() ? document()->page()->theme()->mediaControlsFadeInDuration() : 0;
setInlineStyleProperty(CSSPropertyWebkitTransitionProperty, CSSPropertyOpacity);
setInlineStyleProperty(CSSPropertyWebkitTransitionDuration, duration, CSSPrimitiveValue::CSS_S);
setInlineStyleProperty(CSSPropertyOpacity, 1.0, CSSPrimitiveValue::CSS_NUMBER);
m_opaque = true;
if (m_isDisplayed)
show();
}
void MediaControlEmbeddedPanelElement::makeTransparent()
{
if (!m_opaque)
return;
double duration = document()->page() ? document()->page()->theme()->mediaControlsFadeOutDuration() : 0;
setInlineStyleProperty(CSSPropertyWebkitTransitionProperty, CSSPropertyOpacity);
setInlineStyleProperty(CSSPropertyWebkitTransitionDuration, duration, CSSPrimitiveValue::CSS_S);
setInlineStyleProperty(CSSPropertyOpacity, 0.0, CSSPrimitiveValue::CSS_NUMBER);
m_opaque = false;
startTimer();
}
void MediaControlEmbeddedPanelElement::defaultEventHandler(Event* event)
{
MediaControlDivElement::defaultEventHandler(event);
if (event->isMouseEvent()) {
LayoutPoint location = static_cast<MouseEvent*>(event)->absoluteLocation();
if (event->type() == eventNames().mousedownEvent && event->target() == this) {
startDrag(location);
event->setDefaultHandled();
} else if (event->type() == eventNames().mousemoveEvent && m_isBeingDragged)
continueDrag(location);
else if (event->type() == eventNames().mouseupEvent && m_isBeingDragged) {
continueDrag(location);
endDrag();
event->setDefaultHandled();
}
}
}
void MediaControlEmbeddedPanelElement::setCanBeDragged(bool canBeDragged)
{
if (m_canBeDragged == canBeDragged)
return;
m_canBeDragged = canBeDragged;
if (!canBeDragged)
endDrag();
}
void MediaControlEmbeddedPanelElement::setIsDisplayed(bool isDisplayed)
{
m_isDisplayed = isDisplayed;
}
inline MediaControlFullscreenTimeDisplayContainerElement::MediaControlFullscreenTimeDisplayContainerElement(Document* document)
: MediaControlDivElement(document, MediaControlsPanel)
{
}
PassRefPtr<MediaControlFullscreenTimeDisplayContainerElement> MediaControlFullscreenTimeDisplayContainerElement::create(Document* document)
{
RefPtr<MediaControlFullscreenTimeDisplayContainerElement> element = adoptRef(new MediaControlFullscreenTimeDisplayContainerElement(document));
return element.release();
}
const AtomicString& MediaControlFullscreenTimeDisplayContainerElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-time-display-container", AtomicString::ConstructFromLiteral));
return id;
}
inline MediaControlFullscreenButtonContainerElement::MediaControlFullscreenButtonContainerElement(Document* document)
: MediaControlDivElement(document, MediaControlsPanel)
{
}
PassRefPtr<MediaControlFullscreenButtonContainerElement> MediaControlFullscreenButtonContainerElement::create(Document* document)
{
RefPtr<MediaControlFullscreenButtonContainerElement> element = adoptRef(new MediaControlFullscreenButtonContainerElement(document));
return element.release();
}
const AtomicString& MediaControlFullscreenButtonContainerElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-button-container", AtomicString::ConstructFromLiteral));
return id;
}
inline MediaControlFullscreenButtonDividerElement::MediaControlFullscreenButtonDividerElement(Document* document)
: MediaControlDivElement(document, MediaRewindButton)
{
}
PassRefPtr<MediaControlFullscreenButtonDividerElement> MediaControlFullscreenButtonDividerElement::create(Document* document)
{
RefPtr<MediaControlFullscreenButtonDividerElement> element = adoptRef(new MediaControlFullscreenButtonDividerElement(document));
return element.release();
}
const AtomicString& MediaControlFullscreenButtonDividerElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-button-divider", AtomicString::ConstructFromLiteral));
return id;
}
inline MediaControlPlayButtonContainerElement::MediaControlPlayButtonContainerElement(Document* document)
: MediaControlDivElement(document, MediaControlsPanel)
{
}
PassRefPtr<MediaControlPlayButtonContainerElement> MediaControlPlayButtonContainerElement::create(Document* document)
{
RefPtr<MediaControlPlayButtonContainerElement> element = adoptRef(new MediaControlPlayButtonContainerElement(document));
return element.release();
}
const AtomicString& MediaControlPlayButtonContainerElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-play-button-container", AtomicString::ConstructFromLiteral));
return id;
}
inline MediaControlPlaceholderElement::MediaControlPlaceholderElement(Document* document)
: MediaControlDivElement(document, MediaControlsPanel)
{
}
PassRefPtr<MediaControlPlaceholderElement> MediaControlPlaceholderElement::create(Document* document)
{
RefPtr<MediaControlPlaceholderElement> element = adoptRef(new MediaControlPlaceholderElement(document));
return element.release();
}
const AtomicString& MediaControlPlaceholderElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-placeholder", AtomicString::ConstructFromLiteral));
return id;
}
inline MediaControlFullscreenPlayButtonElement::MediaControlFullscreenPlayButtonElement(Document* document)
: MediaControlInputElement(document, MediaPlayButton)
{
}
PassRefPtr<MediaControlFullscreenPlayButtonElement> MediaControlFullscreenPlayButtonElement::create(Document* document)
{
RefPtr<MediaControlFullscreenPlayButtonElement> button = adoptRef(new MediaControlFullscreenPlayButtonElement(document));
button->ensureUserAgentShadowRoot();
button->setType("button");
return button.release();
}
void MediaControlFullscreenPlayButtonElement::defaultEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
if (mediaController()->canPlay())
mediaController()->play();
else
mediaController()->pause();
updateDisplayType();
event->setDefaultHandled();
}
HTMLInputElement::defaultEventHandler(event);
}
void MediaControlFullscreenPlayButtonElement::updateDisplayType()
{
setDisplayType(mediaController()->canPlay() ? MediaPlayButton : MediaPauseButton);
}
const AtomicString& MediaControlFullscreenPlayButtonElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-play-button", AtomicString::ConstructFromLiteral));
return id;
}
inline MediaControlFullscreenFullscreenButtonElement::MediaControlFullscreenFullscreenButtonElement(Document* document)
: MediaControlInputElement(document, MediaExitFullscreenButton)
{
}
PassRefPtr<MediaControlFullscreenFullscreenButtonElement> MediaControlFullscreenFullscreenButtonElement::create(Document* document)
{
RefPtr<MediaControlFullscreenFullscreenButtonElement> button = adoptRef(new MediaControlFullscreenFullscreenButtonElement(document));
button->ensureUserAgentShadowRoot();
button->setType("button");
button->hide();
return button.release();
}
void MediaControlFullscreenFullscreenButtonElement::defaultEventHandler(Event* event)
{
if (event->type() == eventNames().clickEvent) {
#if ENABLE(FULLSCREEN_API)
// Only use the new full screen API if the fullScreenEnabled setting has
// been explicitly enabled. Otherwise, use the old fullscreen API. This
// allows apps which embed a WebView to retain the existing full screen
// video implementation without requiring them to implement their own full
// screen behavior.
if (document()->settings() && document()->settings()->fullScreenEnabled()) {
if (document()->webkitIsFullScreen() && document()->webkitCurrentFullScreenElement() == parentMediaElement(this))
document()->webkitCancelFullScreen();
else
document()->requestFullScreenForElement(parentMediaElement(this), 0, Document::ExemptIFrameAllowFullScreenRequirement);
} else
#endif
mediaController()->enterFullscreen();
event->setDefaultHandled();
}
HTMLInputElement::defaultEventHandler(event);
}
const AtomicString& MediaControlFullscreenFullscreenButtonElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-fullscreen-button", AtomicString::ConstructFromLiteral));
return id;
}
void MediaControlFullscreenFullscreenButtonElement::setIsFullscreen(bool)
{
setDisplayType(MediaExitFullscreenButton);
}
inline MediaControlFullscreenTimelineContainerElement::MediaControlFullscreenTimelineContainerElement(Document* document)
: MediaControlDivElement(document, MediaTimelineContainer)
{
}
PassRefPtr<MediaControlFullscreenTimelineContainerElement> MediaControlFullscreenTimelineContainerElement::create(Document* document)
{
RefPtr<MediaControlFullscreenTimelineContainerElement> element = adoptRef(new MediaControlFullscreenTimelineContainerElement(document));
element->hide();
return element.release();
}
const AtomicString& MediaControlFullscreenTimelineContainerElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-timeline-container", AtomicString::ConstructFromLiteral));
return id;
}
MediaControlFullscreenTimelineElement::MediaControlFullscreenTimelineElement(Document* document, MediaControls* controls)
: MediaControlInputElement(document, MediaSlider)
, m_controls(controls)
{
}
PassRefPtr<MediaControlFullscreenTimelineElement> MediaControlFullscreenTimelineElement::create(Document* document, MediaControls* controls)
{
ASSERT(controls);
RefPtr<MediaControlFullscreenTimelineElement> timeline = adoptRef(new MediaControlFullscreenTimelineElement(document, controls));
timeline->ensureUserAgentShadowRoot();
timeline->setType("range");
timeline->setAttribute(precisionAttr, "double");
return timeline.release();
}
void MediaControlFullscreenTimelineElement::defaultEventHandler(Event* event)
{
// Left button is 0. Rejects mouse events not from left button.
if (event->isMouseEvent() && static_cast<MouseEvent*>(event)->button())
return;
if (!attached())
return;
if (event->type() == eventNames().mousedownEvent)
mediaController()->beginScrubbing();
if (event->type() == eventNames().mouseupEvent)
mediaController()->endScrubbing();
MediaControlInputElement::defaultEventHandler(event);
if (event->type() == eventNames().mouseoverEvent || event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mousemoveEvent)
return;
double time = value().toDouble();
if (event->type() == eventNames().inputEvent && time != mediaController()->currentTime())
mediaController()->setCurrentTime(time, IGNORE_EXCEPTION);
RenderSlider* slider = toRenderSlider(renderer());
if (slider && slider->inDragMode())
m_controls->updateCurrentTimeDisplay();
}
bool MediaControlFullscreenTimelineElement::willRespondToMouseClickEvents()
{
if (!attached())
return false;
return true;
}
void MediaControlFullscreenTimelineElement::setPosition(double currentTime)
{
setValue(String::number(currentTime));
}
void MediaControlFullscreenTimelineElement::setDuration(double duration)
{
setAttribute(maxAttr, String::number(std::isfinite(duration) ? duration : 0));
}
const AtomicString& MediaControlFullscreenTimelineElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-timeline", AtomicString::ConstructFromLiteral));
return id;
}
PassRefPtr<MediaControlFullscreenTimeRemainingDisplayElement> MediaControlFullscreenTimeRemainingDisplayElement::create(Document* document)
{
return adoptRef(new MediaControlFullscreenTimeRemainingDisplayElement(document));
}
MediaControlFullscreenTimeRemainingDisplayElement::MediaControlFullscreenTimeRemainingDisplayElement(Document* document)
: MediaControlTimeDisplayElement(document, MediaTimeRemainingDisplay)
{
}
const AtomicString& MediaControlFullscreenTimeRemainingDisplayElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-time-remaining-display", AtomicString::ConstructFromLiteral));
return id;
}
PassRefPtr<MediaControlFullscreenCurrentTimeDisplayElement> MediaControlFullscreenCurrentTimeDisplayElement::create(Document* document)
{
return adoptRef(new MediaControlFullscreenCurrentTimeDisplayElement(document));
}
MediaControlFullscreenCurrentTimeDisplayElement::MediaControlFullscreenCurrentTimeDisplayElement(Document* document)
: MediaControlTimeDisplayElement(document, MediaCurrentTimeDisplay)
{
}
const AtomicString& MediaControlFullscreenCurrentTimeDisplayElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-current-time-display", AtomicString::ConstructFromLiteral));
return id;
}
MediaControlAudioMuteButtonElement::MediaControlAudioMuteButtonElement(Document* document, MediaControls* controls)
: MediaControlMuteButtonElement(document, MediaMuteButton)
, m_controls(controls)
{
}
PassRefPtr<MediaControlAudioMuteButtonElement> MediaControlAudioMuteButtonElement::create(Document* document, MediaControls* controls)
{
ASSERT(controls);
RefPtr<MediaControlAudioMuteButtonElement> button = adoptRef(new MediaControlAudioMuteButtonElement(document, controls));
button->ensureUserAgentShadowRoot();
button->setType("button");
return button.release();
}
void MediaControlAudioMuteButtonElement::defaultEventHandler(Event* event)
{
if (event->type() == eventNames().mousedownEvent) {
// We do not mute when the media player volume/mute control is touched.
// Instead we show/hide the volume slider.
static_cast<MediaControlsBlackBerry*>(m_controls)->toggleVolumeSlider();
event->setDefaultHandled();
return;
}
if (event->type() == eventNames().mouseoverEvent)
m_controls->showVolumeSlider();
MediaControlMuteButtonElement::defaultEventHandler(event);
}
const AtomicString& MediaControlAudioMuteButtonElement::shadowPseudoId() const
{
DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-audio-mute-button", AtomicString::ConstructFromLiteral));
return id;
}
MediaControlsBlackBerry::MediaControlsBlackBerry(Document* document)
: MediaControls(document)
, m_buttonContainer(0)
, m_timeDisplayContainer(0)
, m_fullscreenTimeDisplayContainer(0)
, m_fullscreenPlayButton(0)
, m_fullscreenCurrentTimeDisplay(0)
, m_fullscreenTimeline(0)
, m_timeRemainingDisplay(0)
, m_fullscreenTimeRemainingDisplay(0)
, m_timelineContainer(0)
, m_fullscreenTimelineContainer(0)
, m_fullScreenDivider(0)
, m_fullscreenFullScreenButton(0)
, m_muteButton(0)
, m_volumeSliderContainer(0)
, m_embeddedPanel(0)
, m_fullScreenButtonContainer(0)
, m_playButtonContainer(0)
, m_placeholder(0)
{
}
PassRefPtr<MediaControls> MediaControls::create(Document* document)
{
return MediaControlsBlackBerry::createControls(document);
}
PassRefPtr<MediaControlsBlackBerry> MediaControlsBlackBerry::createControls(Document* document)
{
if (!document->page())
return 0;
RefPtr<MediaControlsBlackBerry> controls = adoptRef(new MediaControlsBlackBerry(document));
RefPtr<MediaControlPanelElement> panel = MediaControlPanelElement::create(document);
RefPtr<MediaControlEmbeddedPanelElement> embedPanel = MediaControlEmbeddedPanelElement::create(document);
ExceptionCode ec;
RefPtr<MediaControlPlayButtonElement> playButton = MediaControlPlayButtonElement::create(document);
controls->m_playButton = playButton.get();
embedPanel->appendChild(playButton.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlTimelineContainerElement> timelineContainer = MediaControlTimelineContainerElement::create(document);
RefPtr<MediaControlTimelineElement> timeline = MediaControlTimelineElement::create(document, controls.get());
controls->m_timeline = timeline.get();
timelineContainer->appendChild(timeline.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlTimeDisplayContainerElement> timeDisplayContainer = MediaControlTimeDisplayContainerElement::create(document);
RefPtr<MediaControlCurrentTimeDisplayElement> currentTimeDisplay = MediaControlCurrentTimeDisplayElement::create(document);
controls->m_currentTimeDisplay = currentTimeDisplay.get();
timeDisplayContainer->appendChild(currentTimeDisplay.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlTimeRemainingDisplayElement> timeRemainingDisplay = MediaControlTimeRemainingDisplayElement::create(document);
controls->m_timeRemainingDisplay = timeRemainingDisplay.get();
timeDisplayContainer->appendChild(timeRemainingDisplay.release(), ec, AttachLazily);
if (ec)
return 0;
controls->m_timeDisplayContainer = timeDisplayContainer.get();
timelineContainer->appendChild(timeDisplayContainer.release(), ec, AttachLazily);
if (ec)
return 0;
controls->m_timelineContainer = timelineContainer.get();
embedPanel->appendChild(timelineContainer.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlFullscreenButtonElement> fullScreenButton = MediaControlFullscreenButtonElement::create(document);
controls->m_fullScreenButton = fullScreenButton.get();
embedPanel->appendChild(fullScreenButton.release(), ec, AttachLazily);
if (ec)
return 0;
if (document->page()->theme()->usesMediaControlVolumeSlider()) {
// The mute button and the slider element should be in the same div.
RefPtr<HTMLDivElement> volumeControlContainer = HTMLDivElement::create(document);
RefPtr<MediaControlVolumeSliderContainerElement> volumeSliderContainer = MediaControlVolumeSliderContainerElement::create(document);
RefPtr<MediaControlPanelVolumeSliderElement> slider = MediaControlPanelVolumeSliderElement::create(document);
controls->m_volumeSlider = slider.get();
volumeSliderContainer->appendChild(slider.release(), ec, AttachLazily);
if (ec)
return 0;
controls->m_volumeSliderContainer = volumeSliderContainer.get();
volumeControlContainer->appendChild(volumeSliderContainer.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlAudioMuteButtonElement> muteButton = MediaControlAudioMuteButtonElement::create(document, controls.get());
controls->m_muteButton = muteButton.get();
volumeControlContainer->appendChild(muteButton.release(), ec, AttachLazily);
if (ec)
return 0;
embedPanel->appendChild(volumeControlContainer.release(), ec, AttachLazily);
if (ec)
return 0;
}
RefPtr<MediaControlFullscreenTimelineContainerElement> fullscreenTimelineContainer = MediaControlFullscreenTimelineContainerElement::create(document);
RefPtr<MediaControlFullscreenTimelineElement> fullscreenTimeline = MediaControlFullscreenTimelineElement::create(document, controls.get());
controls->m_fullscreenTimeline = fullscreenTimeline.get();
fullscreenTimelineContainer->appendChild(fullscreenTimeline.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlFullscreenTimeDisplayContainerElement> fullscreenTimeDisplayContainer = MediaControlFullscreenTimeDisplayContainerElement::create(document);
RefPtr<MediaControlFullscreenCurrentTimeDisplayElement> fullscreenCurrentTimeDisplay = MediaControlFullscreenCurrentTimeDisplayElement::create(document);
controls->m_fullscreenCurrentTimeDisplay = fullscreenCurrentTimeDisplay.get();
fullscreenTimeDisplayContainer->appendChild(fullscreenCurrentTimeDisplay.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlFullscreenTimeRemainingDisplayElement> fullscreenTimeRemainingDisplay = MediaControlFullscreenTimeRemainingDisplayElement::create(document);
controls->m_fullscreenTimeRemainingDisplay = fullscreenTimeRemainingDisplay.get();
fullscreenTimeDisplayContainer->appendChild(fullscreenTimeRemainingDisplay.release(), ec, AttachLazily);
if (ec)
return 0;
controls->m_fullscreenTimeDisplayContainer = fullscreenTimeDisplayContainer.get();
fullscreenTimelineContainer->appendChild(fullscreenTimeDisplayContainer.release(), ec, AttachLazily);
if (ec)
return 0;
controls->m_fullscreenTimelineContainer = fullscreenTimelineContainer.get();
panel->appendChild(fullscreenTimelineContainer.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlButtonGroupContainerElement> buttonGroupContainer = MediaControlButtonGroupContainerElement::create(document);
// FIXME: Only create when needed <http://webkit.org/b/57163>
RefPtr<MediaControlFullscreenButtonContainerElement> fullScreenButtonContainer = MediaControlFullscreenButtonContainerElement::create(document);
controls->m_fullScreenButtonContainer = fullScreenButtonContainer.get();
RefPtr<MediaControlFullscreenFullscreenButtonElement> fullscreenFullScreenButton = MediaControlFullscreenFullscreenButtonElement::create(document);
controls->m_fullscreenFullScreenButton = fullscreenFullScreenButton.get();
fullScreenButtonContainer->appendChild(fullscreenFullScreenButton.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlFullscreenButtonDividerElement> fullScreenDivider = MediaControlFullscreenButtonDividerElement::create(document);
controls->m_fullScreenDivider = fullScreenDivider.get();
fullScreenButtonContainer->appendChild(fullScreenDivider.release(), ec, AttachLazily);
if (ec)
return 0;
buttonGroupContainer->appendChild(fullScreenButtonContainer.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlPlayButtonContainerElement> playButtonContainer = MediaControlPlayButtonContainerElement::create(document);
controls->m_playButtonContainer = playButtonContainer.get();
RefPtr<MediaControlFullscreenPlayButtonElement> fullscreenPlayButton = MediaControlFullscreenPlayButtonElement::create(document);
controls->m_fullscreenPlayButton = fullscreenPlayButton.get();
playButtonContainer->appendChild(fullscreenPlayButton.release(), ec, AttachLazily);
if (ec)
return 0;
buttonGroupContainer->appendChild(playButtonContainer.release(), ec, AttachLazily);
if (ec)
return 0;
RefPtr<MediaControlPlaceholderElement> placeholder = MediaControlPlaceholderElement::create(document);
controls->m_placeholder = placeholder.get();
buttonGroupContainer->appendChild(placeholder.release(), ec, AttachLazily);
if (ec)
return 0;
controls->m_buttonContainer = buttonGroupContainer.get();
panel->appendChild(buttonGroupContainer.release(), ec, AttachLazily);
if (ec)
return 0;
if (document->page()->theme()->supportsClosedCaptioning()) {
RefPtr<MediaControlToggleClosedCaptionsButtonElement> toggleClosedCaptionsButton = MediaControlToggleClosedCaptionsButtonElement::create(document, controls.get());
controls->m_toggleClosedCaptionsButton = toggleClosedCaptionsButton.get();
panel->appendChild(toggleClosedCaptionsButton.release(), ec, AttachLazily);
if (ec)
return 0;
}
controls->m_panel = panel.get();
controls->appendChild(panel.release(), ec, AttachLazily);
if (ec)
return 0;
controls->m_embeddedPanel = embedPanel.get();
controls->appendChild(embedPanel.release(), ec, AttachLazily);
if (ec)
return 0;
return controls.release();
}
void MediaControlsBlackBerry::setMediaController(MediaControllerInterface* controller)
{
if (m_mediaController == controller)
return;
MediaControls::setMediaController(controller);
if (m_buttonContainer)
m_buttonContainer->setMediaController(controller);
if (m_timeDisplayContainer)
m_timeDisplayContainer->setMediaController(controller);
if (m_fullscreenTimeDisplayContainer)
m_fullscreenTimeDisplayContainer->setMediaController(controller);
if (m_fullscreenPlayButton)
m_fullscreenPlayButton->setMediaController(controller);
if (m_fullscreenCurrentTimeDisplay)
m_fullscreenCurrentTimeDisplay->setMediaController(controller);
if (m_fullscreenTimeline)
m_fullscreenTimeline->setMediaController(controller);
if (m_timeRemainingDisplay)
m_timeRemainingDisplay->setMediaController(controller);
if (m_fullscreenTimeRemainingDisplay)
m_fullscreenTimeRemainingDisplay->setMediaController(controller);
if (m_timelineContainer)
m_timelineContainer->setMediaController(controller);
if (m_fullscreenTimelineContainer)
m_fullscreenTimelineContainer->setMediaController(controller);
if (m_fullscreenFullScreenButton)
m_fullscreenFullScreenButton->setMediaController(controller);
if (m_muteButton)
m_muteButton->setMediaController(controller);
if (m_volumeSliderContainer)
m_volumeSliderContainer->setMediaController(controller);
if (m_embeddedPanel)
m_embeddedPanel->setMediaController(controller);
reset();
}
void MediaControlsBlackBerry::show()
{
if (m_isFullscreen) {
m_panel->setIsDisplayed(true);
m_panel->show();
} else {
m_embeddedPanel->setIsDisplayed(true);
m_embeddedPanel->show();
}
}
void MediaControlsBlackBerry::hide()
{
if (m_isFullscreen) {
m_panel->setIsDisplayed(false);
m_panel->hide();
} else {
m_embeddedPanel->setIsDisplayed(false);
m_embeddedPanel->hide();
m_volumeSliderContainer->hide();
}
}
void MediaControlsBlackBerry::makeOpaque()
{
if (m_isFullscreen)
m_panel->makeOpaque();
else
m_embeddedPanel->makeOpaque();
}
void MediaControlsBlackBerry::makeTransparent()
{
if (m_isFullscreen)
m_panel->makeTransparent();
else {
m_embeddedPanel->makeTransparent();
m_volumeSliderContainer->hide();
}
}
void MediaControlsBlackBerry::reset()
{
Page* page = document()->page();
if (!page)
return;
updateStatusDisplay();
if (m_fullScreenButton) {
if (m_mediaController->supportsFullscreen())
m_fullScreenButton->show();
else
m_fullScreenButton->hide();
}
if (m_fullscreenFullScreenButton) {
if (m_mediaController->supportsFullscreen())
m_fullscreenFullScreenButton->show();
else
m_fullscreenFullScreenButton->hide();
}
double duration = m_mediaController->duration();
if (std::isfinite(duration) || page->theme()->hasOwnDisabledStateHandlingFor(MediaSliderPart)) {
double now = m_mediaController->currentTime();
m_timeline->setDuration(duration);
m_fullscreenTimeline->setDuration(duration);
m_timelineContainer->show();
m_fullscreenTimelineContainer->show();
m_timeline->setPosition(now);
m_fullscreenTimeline->setPosition(now);
updateCurrentTimeDisplay();
} else {
m_timelineContainer->hide();
m_fullscreenTimelineContainer->hide();
}
if (m_mediaController->hasAudio() || page->theme()->hasOwnDisabledStateHandlingFor(MediaMuteButtonPart))
m_muteButton->show();
else
m_muteButton->hide();
if (m_volumeSlider)
setSliderVolume();
if (m_toggleClosedCaptionsButton) {
if (m_mediaController->hasClosedCaptions())
m_toggleClosedCaptionsButton->show();
else
m_toggleClosedCaptionsButton->hide();
}
if (m_playButton)
m_playButton->updateDisplayType();
if (m_fullscreenPlayButton)
m_fullscreenPlayButton->updateDisplayType();
makeOpaque();
}
void MediaControlsBlackBerry::bufferingProgressed()
{
// We only need to update buffering progress when paused, during normal
// playback playbackProgressed() will take care of it.
if (m_mediaController->paused()) {
double now = m_mediaController->currentTime();
m_timeline->setPosition(now);
m_fullscreenTimeline->setPosition(now);
}
}
void MediaControlsBlackBerry::playbackStarted()
{
double now = m_mediaController->currentTime();
m_playButton->updateDisplayType();
m_fullscreenPlayButton->updateDisplayType();
m_timeline->setPosition(now);
m_fullscreenTimeline->setPosition(now);
updateCurrentTimeDisplay();
if (m_isFullscreen)
startHideFullscreenControlsTimer();
}
void MediaControlsBlackBerry::playbackProgressed()
{
double now = m_mediaController->currentTime();
m_timeline->setPosition(now);
m_fullscreenTimeline->setPosition(now);
updateCurrentTimeDisplay();
if (!m_isMouseOverControls && m_mediaController->hasVideo())
makeTransparent();
}
void MediaControlsBlackBerry::playbackStopped()
{
double now = m_mediaController->currentTime();
m_playButton->updateDisplayType();
m_fullscreenPlayButton->updateDisplayType();
m_timeline->setPosition(now);
m_fullscreenTimeline->setPosition(now);
updateCurrentTimeDisplay();
makeOpaque();
stopHideFullscreenControlsTimer();
}
void MediaControlsBlackBerry::updateCurrentTimeDisplay()
{
double now = m_mediaController->currentTime();
double duration = m_mediaController->duration();
Page* page = document()->page();
if (!page)
return;
// Allow the theme to format the time.
m_currentTimeDisplay->setInnerText(page->theme()->formatMediaControlsCurrentTime(now, duration), IGNORE_EXCEPTION);
m_currentTimeDisplay->setCurrentValue(now);
m_fullscreenCurrentTimeDisplay->setInnerText(page->theme()->formatMediaControlsCurrentTime(now, duration), IGNORE_EXCEPTION);
m_fullscreenCurrentTimeDisplay->setCurrentValue(now);
m_timeRemainingDisplay->setInnerText(page->theme()->formatMediaControlsRemainingTime(now, duration), IGNORE_EXCEPTION);
m_timeRemainingDisplay->setCurrentValue(now - duration);
m_fullscreenTimeRemainingDisplay->setInnerText(page->theme()->formatMediaControlsRemainingTime(now, duration), IGNORE_EXCEPTION);
m_fullscreenTimeRemainingDisplay->setCurrentValue(now - duration);
}
void MediaControlsBlackBerry::reportedError()
{
Page* page = document()->page();
if (!page)
return;
if (!page->theme()->hasOwnDisabledStateHandlingFor(MediaSliderPart)) {
m_timelineContainer->hide();
m_fullscreenTimelineContainer->hide();
}
if (!page->theme()->hasOwnDisabledStateHandlingFor(MediaMuteButtonPart))
m_muteButton->hide();
if (m_fullScreenButton)
m_fullScreenButton->hide();
if (m_fullScreenDivider)
m_fullScreenDivider->hide();
if (m_fullscreenFullScreenButton)
m_fullscreenFullScreenButton->hide();
if (m_volumeSliderContainer)
m_volumeSliderContainer->hide();
if (m_toggleClosedCaptionsButton && !page->theme()->hasOwnDisabledStateHandlingFor(MediaToggleClosedCaptionsButtonPart))
m_toggleClosedCaptionsButton->hide();
}
void MediaControlsBlackBerry::changedMute()
{
m_muteButton->changedMute();
}
void MediaControlsBlackBerry::enteredFullscreen()
{
MediaControls::enteredFullscreen();
m_panel->setCanBeDragged(true);
m_embeddedPanel->setCanBeDragged(true);
if (m_fullscreenFullScreenButton)
m_fullscreenFullScreenButton->setIsFullscreen(true);
}
void MediaControlsBlackBerry::exitedFullscreen()
{
m_panel->setCanBeDragged(false);
m_embeddedPanel->setCanBeDragged(false);
if (m_fullscreenFullScreenButton)
m_fullscreenFullScreenButton->setIsFullscreen(false);
// We will keep using the panel, but we want it to go back to the standard position.
// This will matter right away because we use the panel even when not fullscreen.
// And if we reenter fullscreen we also want the panel in the standard position.
m_panel->resetPosition();
m_embeddedPanel->resetPosition();
MediaControls::exitedFullscreen();
}
void MediaControlsBlackBerry::showVolumeSlider()
{
if (!m_mediaController->hasAudio())
return;
if (m_volumeSliderContainer)
m_volumeSliderContainer->show();
}
void MediaControlsBlackBerry::toggleVolumeSlider()
{
if (!m_mediaController->hasAudio())
return;
if (m_volumeSliderContainer) {
if (m_volumeSliderContainer->renderer() && m_volumeSliderContainer->renderer()->visibleToHitTesting())
m_volumeSliderContainer->hide();
else
m_volumeSliderContainer->show();
}
}
bool MediaControlsBlackBerry::shouldHideControls()
{
if (m_isFullscreen)
return !m_panel->hovered();
return !m_embeddedPanel->hovered();
}
}
#endif