2 * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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 Computer, 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.
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.
31 #include "core/html/shadow/MediaControlElements.h"
33 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
34 #include "core/InputTypeNames.h"
35 #include "core/dom/DOMTokenList.h"
36 #include "core/dom/shadow/ShadowRoot.h"
37 #include "core/events/MouseEvent.h"
38 #include "core/frame/LocalFrame.h"
39 #include "core/html/HTMLVideoElement.h"
40 #include "core/html/MediaController.h"
41 #include "core/html/TimeRanges.h"
42 #include "core/html/shadow/MediaControls.h"
43 #include "core/input/EventHandler.h"
44 #include "core/layout/LayoutSlider.h"
45 #include "core/layout/LayoutTheme.h"
46 #include "core/layout/LayoutVideo.h"
47 #include "platform/RuntimeEnabledFeatures.h"
51 using namespace HTMLNames
;
53 // This is the duration from mediaControls.css
54 static const double fadeOutDuration
= 0.3;
56 static bool isUserInteractionEvent(Event
* event
)
58 const AtomicString
& type
= event
->type();
59 return type
== EventTypeNames::mousedown
60 || type
== EventTypeNames::mouseup
61 || type
== EventTypeNames::click
62 || type
== EventTypeNames::dblclick
63 || event
->isKeyboardEvent()
64 || event
->isTouchEvent();
67 // Sliders (the volume control and timeline) need to capture some additional events used when dragging the thumb.
68 static bool isUserInteractionEventForSlider(Event
* event
, LayoutObject
* layoutObject
)
70 // It is unclear if this can be converted to isUserInteractionEvent(), since
71 // mouse* events seem to be eaten during a drag anyway. crbug.com/516416 .
72 if (isUserInteractionEvent(event
))
75 // Some events are only captured during a slider drag.
76 LayoutSlider
* slider
= toLayoutSlider(layoutObject
);
77 if (slider
&& !slider
->inDragMode())
80 const AtomicString
& type
= event
->type();
81 return type
== EventTypeNames::mouseover
82 || type
== EventTypeNames::mouseout
83 || type
== EventTypeNames::mousemove
;
87 MediaControlPanelElement::MediaControlPanelElement(MediaControls
& mediaControls
)
88 : MediaControlDivElement(mediaControls
, MediaControlsPanel
)
89 , m_isDisplayed(false)
91 , m_transitionTimer(this, &MediaControlPanelElement::transitionTimerFired
)
95 PassRefPtrWillBeRawPtr
<MediaControlPanelElement
> MediaControlPanelElement::create(MediaControls
& mediaControls
)
97 RefPtrWillBeRawPtr
<MediaControlPanelElement
> panel
= adoptRefWillBeNoop(new MediaControlPanelElement(mediaControls
));
98 panel
->setShadowPseudoId(AtomicString("-webkit-media-controls-panel", AtomicString::ConstructFromLiteral
));
99 return panel
.release();
102 void MediaControlPanelElement::defaultEventHandler(Event
* event
)
104 // Suppress the media element activation behavior (toggle play/pause) when
105 // any part of the control panel is clicked.
106 if (event
->type() == EventTypeNames::click
) {
107 event
->setDefaultHandled();
110 HTMLDivElement::defaultEventHandler(event
);
113 void MediaControlPanelElement::startTimer()
117 // The timer is required to set the property display:'none' on the panel,
118 // such that captions are correctly displayed at the bottom of the video
119 // at the end of the fadeout transition.
120 // FIXME: Racing a transition with a setTimeout like this is wrong.
121 m_transitionTimer
.startOneShot(fadeOutDuration
, FROM_HERE
);
124 void MediaControlPanelElement::stopTimer()
126 if (m_transitionTimer
.isActive())
127 m_transitionTimer
.stop();
130 void MediaControlPanelElement::transitionTimerFired(Timer
<MediaControlPanelElement
>*)
138 void MediaControlPanelElement::didBecomeVisible()
140 ASSERT(m_isDisplayed
&& m_opaque
);
141 mediaElement().mediaControlsDidBecomeVisible();
144 void MediaControlPanelElement::makeOpaque()
149 setInlineStyleProperty(CSSPropertyOpacity
, 1.0, CSSPrimitiveValue::UnitType::Number
);
158 void MediaControlPanelElement::makeTransparent()
163 setInlineStyleProperty(CSSPropertyOpacity
, 0.0, CSSPrimitiveValue::UnitType::Number
);
169 void MediaControlPanelElement::setIsDisplayed(bool isDisplayed
)
171 if (m_isDisplayed
== isDisplayed
)
174 m_isDisplayed
= isDisplayed
;
175 if (m_isDisplayed
&& m_opaque
)
179 bool MediaControlPanelElement::keepEventInNode(Event
* event
)
181 return isUserInteractionEvent(event
);
184 // ----------------------------
186 MediaControlPanelEnclosureElement::MediaControlPanelEnclosureElement(MediaControls
& mediaControls
)
187 // Mapping onto same MediaControlElementType as panel element, since it has similar properties.
188 : MediaControlDivElement(mediaControls
, MediaControlsPanel
)
192 PassRefPtrWillBeRawPtr
<MediaControlPanelEnclosureElement
> MediaControlPanelEnclosureElement::create(MediaControls
& mediaControls
)
194 RefPtrWillBeRawPtr
<MediaControlPanelEnclosureElement
> enclosure
= adoptRefWillBeNoop(new MediaControlPanelEnclosureElement(mediaControls
));
195 enclosure
->setShadowPseudoId(AtomicString("-webkit-media-controls-enclosure", AtomicString::ConstructFromLiteral
));
196 return enclosure
.release();
199 // ----------------------------
201 MediaControlOverlayEnclosureElement::MediaControlOverlayEnclosureElement(MediaControls
& mediaControls
)
202 // Mapping onto same MediaControlElementType as panel element, since it has similar properties.
203 : MediaControlDivElement(mediaControls
, MediaControlsPanel
)
207 PassRefPtrWillBeRawPtr
<MediaControlOverlayEnclosureElement
> MediaControlOverlayEnclosureElement::create(MediaControls
& mediaControls
)
209 RefPtrWillBeRawPtr
<MediaControlOverlayEnclosureElement
> enclosure
= adoptRefWillBeNoop(new MediaControlOverlayEnclosureElement(mediaControls
));
210 enclosure
->setShadowPseudoId(AtomicString("-webkit-media-controls-overlay-enclosure", AtomicString::ConstructFromLiteral
));
211 return enclosure
.release();
214 void* MediaControlOverlayEnclosureElement::preDispatchEventHandler(Event
* event
)
216 // When the media element is clicked or touched we want to make the overlay cast button visible
217 // (if the other requirements are right) even if JavaScript is doing its own handling of the event.
218 // Doing it in preDispatchEventHandler prevents any interference from JavaScript.
219 // Note that we can't simply test for click, since JS handling of touch events can prevent their translation to click events.
220 if (event
&& (event
->type() == EventTypeNames::click
|| event
->type() == EventTypeNames::touchstart
) && mediaElement().hasRemoteRoutes() && !mediaElement().shouldShowControls())
221 mediaControls().showOverlayCastButton();
222 return MediaControlDivElement::preDispatchEventHandler(event
);
226 // ----------------------------
228 MediaControlMuteButtonElement::MediaControlMuteButtonElement(MediaControls
& mediaControls
)
229 : MediaControlInputElement(mediaControls
, MediaMuteButton
)
233 PassRefPtrWillBeRawPtr
<MediaControlMuteButtonElement
> MediaControlMuteButtonElement::create(MediaControls
& mediaControls
)
235 RefPtrWillBeRawPtr
<MediaControlMuteButtonElement
> button
= adoptRefWillBeNoop(new MediaControlMuteButtonElement(mediaControls
));
236 button
->ensureUserAgentShadowRoot();
237 button
->setType(InputTypeNames::button
);
238 button
->setShadowPseudoId(AtomicString("-webkit-media-controls-mute-button", AtomicString::ConstructFromLiteral
));
239 return button
.release();
242 void MediaControlMuteButtonElement::defaultEventHandler(Event
* event
)
244 if (event
->type() == EventTypeNames::click
) {
245 mediaElement().setMuted(!mediaElement().muted());
246 event
->setDefaultHandled();
249 HTMLInputElement::defaultEventHandler(event
);
252 void MediaControlMuteButtonElement::updateDisplayType()
254 setDisplayType(mediaElement().muted() ? MediaUnMuteButton
: MediaMuteButton
);
257 // ----------------------------
259 MediaControlPlayButtonElement::MediaControlPlayButtonElement(MediaControls
& mediaControls
)
260 : MediaControlInputElement(mediaControls
, MediaPlayButton
)
264 PassRefPtrWillBeRawPtr
<MediaControlPlayButtonElement
> MediaControlPlayButtonElement::create(MediaControls
& mediaControls
)
266 RefPtrWillBeRawPtr
<MediaControlPlayButtonElement
> button
= adoptRefWillBeNoop(new MediaControlPlayButtonElement(mediaControls
));
267 button
->ensureUserAgentShadowRoot();
268 button
->setType(InputTypeNames::button
);
269 button
->setShadowPseudoId(AtomicString("-webkit-media-controls-play-button", AtomicString::ConstructFromLiteral
));
270 return button
.release();
273 void MediaControlPlayButtonElement::defaultEventHandler(Event
* event
)
275 if (event
->type() == EventTypeNames::click
) {
276 mediaElement().togglePlayState();
278 event
->setDefaultHandled();
280 HTMLInputElement::defaultEventHandler(event
);
283 void MediaControlPlayButtonElement::updateDisplayType()
285 setDisplayType(mediaElement().togglePlayStateWillPlay() ? MediaPlayButton
: MediaPauseButton
);
288 // ----------------------------
290 MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(MediaControls
& mediaControls
)
291 : MediaControlInputElement(mediaControls
, MediaOverlayPlayButton
)
295 PassRefPtrWillBeRawPtr
<MediaControlOverlayPlayButtonElement
> MediaControlOverlayPlayButtonElement::create(MediaControls
& mediaControls
)
297 RefPtrWillBeRawPtr
<MediaControlOverlayPlayButtonElement
> button
= adoptRefWillBeNoop(new MediaControlOverlayPlayButtonElement(mediaControls
));
298 button
->ensureUserAgentShadowRoot();
299 button
->setType(InputTypeNames::button
);
300 button
->setShadowPseudoId(AtomicString("-webkit-media-controls-overlay-play-button", AtomicString::ConstructFromLiteral
));
301 return button
.release();
304 void MediaControlOverlayPlayButtonElement::defaultEventHandler(Event
* event
)
306 if (event
->type() == EventTypeNames::click
&& mediaElement().togglePlayStateWillPlay()) {
307 mediaElement().togglePlayState();
309 event
->setDefaultHandled();
313 void MediaControlOverlayPlayButtonElement::updateDisplayType()
315 setIsWanted(mediaElement().shouldShowControls() && mediaElement().togglePlayStateWillPlay());
318 bool MediaControlOverlayPlayButtonElement::keepEventInNode(Event
* event
)
320 return isUserInteractionEvent(event
);
324 // ----------------------------
326 MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(MediaControls
& mediaControls
)
327 : MediaControlInputElement(mediaControls
, MediaShowClosedCaptionsButton
)
331 PassRefPtrWillBeRawPtr
<MediaControlToggleClosedCaptionsButtonElement
> MediaControlToggleClosedCaptionsButtonElement::create(MediaControls
& mediaControls
)
333 RefPtrWillBeRawPtr
<MediaControlToggleClosedCaptionsButtonElement
> button
= adoptRefWillBeNoop(new MediaControlToggleClosedCaptionsButtonElement(mediaControls
));
334 button
->ensureUserAgentShadowRoot();
335 button
->setType(InputTypeNames::button
);
336 button
->setShadowPseudoId(AtomicString("-webkit-media-controls-toggle-closed-captions-button", AtomicString::ConstructFromLiteral
));
337 button
->setIsWanted(false);
338 return button
.release();
341 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
343 bool captionsVisible
= mediaElement().closedCaptionsVisible();
344 setDisplayType(captionsVisible
? MediaHideClosedCaptionsButton
: MediaShowClosedCaptionsButton
);
345 setChecked(captionsVisible
);
348 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event
* event
)
350 if (event
->type() == EventTypeNames::click
) {
351 mediaElement().setClosedCaptionsVisible(!mediaElement().closedCaptionsVisible());
352 setChecked(mediaElement().closedCaptionsVisible());
354 event
->setDefaultHandled();
357 HTMLInputElement::defaultEventHandler(event
);
360 // ----------------------------
362 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls
& mediaControls
)
363 : MediaControlInputElement(mediaControls
, MediaSlider
)
367 PassRefPtrWillBeRawPtr
<MediaControlTimelineElement
> MediaControlTimelineElement::create(MediaControls
& mediaControls
)
369 RefPtrWillBeRawPtr
<MediaControlTimelineElement
> timeline
= adoptRefWillBeNoop(new MediaControlTimelineElement(mediaControls
));
370 timeline
->ensureUserAgentShadowRoot();
371 timeline
->setType(InputTypeNames::range
);
372 timeline
->setAttribute(stepAttr
, "any");
373 timeline
->setShadowPseudoId(AtomicString("-webkit-media-controls-timeline", AtomicString::ConstructFromLiteral
));
374 return timeline
.release();
377 void MediaControlTimelineElement::defaultEventHandler(Event
* event
)
379 if (event
->isMouseEvent() && toMouseEvent(event
)->button() != LeftButton
)
382 if (!inDocument() || !document().isActive())
385 if (event
->type() == EventTypeNames::mousedown
)
386 mediaControls().beginScrubbing();
388 if (event
->type() == EventTypeNames::mouseup
)
389 mediaControls().endScrubbing();
391 MediaControlInputElement::defaultEventHandler(event
);
393 if (event
->type() == EventTypeNames::mouseover
|| event
->type() == EventTypeNames::mouseout
|| event
->type() == EventTypeNames::mousemove
)
396 double time
= value().toDouble();
397 if (event
->type() == EventTypeNames::input
) {
398 // FIXME: This will need to take the timeline offset into consideration
399 // once that concept is supported, see https://crbug.com/312699
400 if (mediaElement().controller()) {
401 if (mediaElement().controller()->seekable()->contain(time
))
402 mediaElement().controller()->setCurrentTime(time
);
403 } else if (mediaElement().seekable()->contain(time
)) {
404 mediaElement().setCurrentTime(time
, IGNORE_EXCEPTION
);
408 LayoutSlider
* slider
= toLayoutSlider(layoutObject());
409 if (slider
&& slider
->inDragMode())
410 mediaControls().updateCurrentTimeDisplay();
413 bool MediaControlTimelineElement::willRespondToMouseClickEvents()
415 return inDocument() && document().isActive();
418 void MediaControlTimelineElement::setPosition(double currentTime
)
420 setValue(String::number(currentTime
));
422 if (LayoutObject
* layoutObject
= this->layoutObject())
423 layoutObject
->setShouldDoFullPaintInvalidation();
426 void MediaControlTimelineElement::setDuration(double duration
)
428 setFloatingPointAttribute(maxAttr
, std::isfinite(duration
) ? duration
: 0);
430 if (LayoutObject
* layoutObject
= this->layoutObject())
431 layoutObject
->setShouldDoFullPaintInvalidation();
434 bool MediaControlTimelineElement::keepEventInNode(Event
* event
)
436 return isUserInteractionEventForSlider(event
, layoutObject());
439 // ----------------------------
441 MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(MediaControls
& mediaControls
)
442 : MediaControlInputElement(mediaControls
, MediaVolumeSlider
)
446 PassRefPtrWillBeRawPtr
<MediaControlVolumeSliderElement
> MediaControlVolumeSliderElement::create(MediaControls
& mediaControls
)
448 RefPtrWillBeRawPtr
<MediaControlVolumeSliderElement
> slider
= adoptRefWillBeNoop(new MediaControlVolumeSliderElement(mediaControls
));
449 slider
->ensureUserAgentShadowRoot();
450 slider
->setType(InputTypeNames::range
);
451 slider
->setAttribute(stepAttr
, "any");
452 slider
->setAttribute(maxAttr
, "1");
453 slider
->setShadowPseudoId(AtomicString("-webkit-media-controls-volume-slider", AtomicString::ConstructFromLiteral
));
454 return slider
.release();
457 void MediaControlVolumeSliderElement::defaultEventHandler(Event
* event
)
459 if (event
->isMouseEvent() && toMouseEvent(event
)->button() != LeftButton
)
462 if (!inDocument() || !document().isActive())
465 MediaControlInputElement::defaultEventHandler(event
);
467 if (event
->type() == EventTypeNames::mouseover
|| event
->type() == EventTypeNames::mouseout
|| event
->type() == EventTypeNames::mousemove
)
470 double volume
= value().toDouble();
471 mediaElement().setVolume(volume
, ASSERT_NO_EXCEPTION
);
472 mediaElement().setMuted(false);
475 bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents()
477 if (!inDocument() || !document().isActive())
480 return MediaControlInputElement::willRespondToMouseMoveEvents();
483 bool MediaControlVolumeSliderElement::willRespondToMouseClickEvents()
485 if (!inDocument() || !document().isActive())
488 return MediaControlInputElement::willRespondToMouseClickEvents();
491 void MediaControlVolumeSliderElement::setVolume(double volume
)
493 if (value().toDouble() != volume
)
494 setValue(String::number(volume
));
497 bool MediaControlVolumeSliderElement::keepEventInNode(Event
* event
)
499 return isUserInteractionEventForSlider(event
, layoutObject());
502 // ----------------------------
504 MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(MediaControls
& mediaControls
)
505 : MediaControlInputElement(mediaControls
, MediaEnterFullscreenButton
)
509 PassRefPtrWillBeRawPtr
<MediaControlFullscreenButtonElement
> MediaControlFullscreenButtonElement::create(MediaControls
& mediaControls
)
511 RefPtrWillBeRawPtr
<MediaControlFullscreenButtonElement
> button
= adoptRefWillBeNoop(new MediaControlFullscreenButtonElement(mediaControls
));
512 button
->ensureUserAgentShadowRoot();
513 button
->setType(InputTypeNames::button
);
514 button
->setShadowPseudoId(AtomicString("-webkit-media-controls-fullscreen-button", AtomicString::ConstructFromLiteral
));
515 button
->setIsWanted(false);
516 return button
.release();
519 void MediaControlFullscreenButtonElement::defaultEventHandler(Event
* event
)
521 if (event
->type() == EventTypeNames::click
) {
522 if (mediaElement().isFullscreen())
523 mediaElement().exitFullscreen();
525 mediaElement().enterFullscreen();
526 event
->setDefaultHandled();
528 HTMLInputElement::defaultEventHandler(event
);
531 void MediaControlFullscreenButtonElement::setIsFullscreen(bool isFullscreen
)
533 setDisplayType(isFullscreen
? MediaExitFullscreenButton
: MediaEnterFullscreenButton
);
536 // ----------------------------
538 MediaControlCastButtonElement::MediaControlCastButtonElement(MediaControls
& mediaControls
, bool isOverlayButton
)
539 : MediaControlInputElement(mediaControls
, MediaCastOnButton
), m_isOverlayButton(isOverlayButton
)
541 setIsPlayingRemotely(false);
544 PassRefPtrWillBeRawPtr
<MediaControlCastButtonElement
> MediaControlCastButtonElement::create(MediaControls
& mediaControls
, bool isOverlayButton
)
546 RefPtrWillBeRawPtr
<MediaControlCastButtonElement
> button
= adoptRefWillBeNoop(new MediaControlCastButtonElement(mediaControls
, isOverlayButton
));
547 button
->ensureUserAgentShadowRoot();
548 button
->setType(InputTypeNames::button
);
549 return button
.release();
552 void MediaControlCastButtonElement::defaultEventHandler(Event
* event
)
554 if (event
->type() == EventTypeNames::click
) {
555 if (mediaElement().isPlayingRemotely()) {
556 mediaElement().requestRemotePlaybackControl();
558 mediaElement().requestRemotePlayback();
561 HTMLInputElement::defaultEventHandler(event
);
564 const AtomicString
& MediaControlCastButtonElement::shadowPseudoId() const
566 DEFINE_STATIC_LOCAL(AtomicString
, id_nonOverlay
, ("-internal-media-controls-cast-button", AtomicString::ConstructFromLiteral
));
567 DEFINE_STATIC_LOCAL(AtomicString
, id_overlay
, ("-internal-media-controls-overlay-cast-button", AtomicString::ConstructFromLiteral
));
568 return m_isOverlayButton
? id_overlay
: id_nonOverlay
;
571 void MediaControlCastButtonElement::setIsPlayingRemotely(bool isPlayingRemotely
)
573 if (isPlayingRemotely
) {
574 if (m_isOverlayButton
) {
575 setDisplayType(MediaOverlayCastOnButton
);
577 setDisplayType(MediaCastOnButton
);
580 if (m_isOverlayButton
) {
581 setDisplayType(MediaOverlayCastOffButton
);
583 setDisplayType(MediaCastOffButton
);
588 bool MediaControlCastButtonElement::keepEventInNode(Event
* event
)
590 return isUserInteractionEvent(event
);
593 // ----------------------------
595 MediaControlTimeRemainingDisplayElement::MediaControlTimeRemainingDisplayElement(MediaControls
& mediaControls
)
596 : MediaControlTimeDisplayElement(mediaControls
, MediaTimeRemainingDisplay
)
600 PassRefPtrWillBeRawPtr
<MediaControlTimeRemainingDisplayElement
> MediaControlTimeRemainingDisplayElement::create(MediaControls
& mediaControls
)
602 RefPtrWillBeRawPtr
<MediaControlTimeRemainingDisplayElement
> element
= adoptRefWillBeNoop(new MediaControlTimeRemainingDisplayElement(mediaControls
));
603 element
->setShadowPseudoId(AtomicString("-webkit-media-controls-time-remaining-display", AtomicString::ConstructFromLiteral
));
604 return element
.release();
607 // ----------------------------
609 MediaControlCurrentTimeDisplayElement::MediaControlCurrentTimeDisplayElement(MediaControls
& mediaControls
)
610 : MediaControlTimeDisplayElement(mediaControls
, MediaCurrentTimeDisplay
)
614 PassRefPtrWillBeRawPtr
<MediaControlCurrentTimeDisplayElement
> MediaControlCurrentTimeDisplayElement::create(MediaControls
& mediaControls
)
616 RefPtrWillBeRawPtr
<MediaControlCurrentTimeDisplayElement
> element
= adoptRefWillBeNoop(new MediaControlCurrentTimeDisplayElement(mediaControls
));
617 element
->setShadowPseudoId(AtomicString("-webkit-media-controls-current-time-display", AtomicString::ConstructFromLiteral
));
618 return element
.release();