Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / shadow / MediaControlElements.cpp
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 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.
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 #include "core/html/shadow/MediaControlElements.h"
32
33 #include "RuntimeEnabledFeatures.h"
34 #include "bindings/v8/ExceptionStatePlaceholder.h"
35 #include "core/dom/DOMTokenList.h"
36 #include "core/dom/FullscreenElementStack.h"
37 #include "core/dom/shadow/ShadowRoot.h"
38 #include "core/events/MouseEvent.h"
39 #include "core/frame/LocalFrame.h"
40 #include "core/html/HTMLVideoElement.h"
41 #include "core/html/MediaController.h"
42 #include "core/html/shadow/MediaControls.h"
43 #include "core/html/track/TextTrack.h"
44 #include "core/html/track/vtt/VTTRegionList.h"
45 #include "core/page/EventHandler.h"
46 #include "core/rendering/RenderMediaControlElements.h"
47 #include "core/rendering/RenderSlider.h"
48 #include "core/rendering/RenderTheme.h"
49 #include "core/rendering/RenderVideo.h"
50
51 namespace WebCore {
52
53 using namespace HTMLNames;
54
55 static const AtomicString& getMediaControlCurrentTimeDisplayElementShadowPseudoId();
56 static const AtomicString& getMediaControlTimeRemainingDisplayElementShadowPseudoId();
57
58 static const double fadeInDuration = 0.1;
59 static const double fadeOutDuration = 0.3;
60
61 MediaControlPanelElement::MediaControlPanelElement(MediaControls& mediaControls)
62     : MediaControlDivElement(mediaControls, MediaControlsPanel)
63     , m_isDisplayed(false)
64     , m_opaque(true)
65     , m_transitionTimer(this, &MediaControlPanelElement::transitionTimerFired)
66 {
67 }
68
69 PassRefPtr<MediaControlPanelElement> MediaControlPanelElement::create(MediaControls& mediaControls)
70 {
71     return adoptRef(new MediaControlPanelElement(mediaControls));
72 }
73
74 const AtomicString& MediaControlPanelElement::shadowPseudoId() const
75 {
76     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-panel", AtomicString::ConstructFromLiteral));
77     return id;
78 }
79
80 void MediaControlPanelElement::defaultEventHandler(Event* event)
81 {
82     // Suppress the media element activation behavior (toggle play/pause) when
83     // any part of the control panel is clicked.
84     if (event->type() == EventTypeNames::click) {
85         event->setDefaultHandled();
86         return;
87     }
88     HTMLDivElement::defaultEventHandler(event);
89 }
90
91 void MediaControlPanelElement::startTimer()
92 {
93     stopTimer();
94
95     // The timer is required to set the property display:'none' on the panel,
96     // such that captions are correctly displayed at the bottom of the video
97     // at the end of the fadeout transition.
98     // FIXME: Racing a transition with a setTimeout like this is wrong.
99     m_transitionTimer.startOneShot(fadeOutDuration, FROM_HERE);
100 }
101
102 void MediaControlPanelElement::stopTimer()
103 {
104     if (m_transitionTimer.isActive())
105         m_transitionTimer.stop();
106 }
107
108 void MediaControlPanelElement::transitionTimerFired(Timer<MediaControlPanelElement>*)
109 {
110     if (!m_opaque)
111         hide();
112
113     stopTimer();
114 }
115
116 void MediaControlPanelElement::makeOpaque()
117 {
118     if (m_opaque)
119         return;
120
121     setInlineStyleProperty(CSSPropertyTransitionProperty, CSSPropertyOpacity);
122     setInlineStyleProperty(CSSPropertyTransitionDuration, fadeInDuration, CSSPrimitiveValue::CSS_S);
123     setInlineStyleProperty(CSSPropertyOpacity, 1.0, CSSPrimitiveValue::CSS_NUMBER);
124
125     m_opaque = true;
126
127     if (m_isDisplayed)
128         show();
129 }
130
131 void MediaControlPanelElement::makeTransparent()
132 {
133     if (!m_opaque)
134         return;
135
136     setInlineStyleProperty(CSSPropertyTransitionProperty, CSSPropertyOpacity);
137     setInlineStyleProperty(CSSPropertyTransitionDuration, fadeOutDuration, CSSPrimitiveValue::CSS_S);
138     setInlineStyleProperty(CSSPropertyOpacity, 0.0, CSSPrimitiveValue::CSS_NUMBER);
139
140     m_opaque = false;
141     startTimer();
142 }
143
144 void MediaControlPanelElement::setIsDisplayed(bool isDisplayed)
145 {
146     m_isDisplayed = isDisplayed;
147 }
148
149 // ----------------------------
150
151 MediaControlPanelEnclosureElement::MediaControlPanelEnclosureElement(MediaControls& mediaControls)
152     // Mapping onto same MediaControlElementType as panel element, since it has similar properties.
153     : MediaControlDivElement(mediaControls, MediaControlsPanel)
154 {
155 }
156
157 PassRefPtr<MediaControlPanelEnclosureElement> MediaControlPanelEnclosureElement::create(MediaControls& mediaControls)
158 {
159     return adoptRef(new MediaControlPanelEnclosureElement(mediaControls));
160 }
161
162 const AtomicString& MediaControlPanelEnclosureElement::shadowPseudoId() const
163 {
164     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-enclosure", AtomicString::ConstructFromLiteral));
165     return id;
166 }
167
168 // ----------------------------
169
170 MediaControlOverlayEnclosureElement::MediaControlOverlayEnclosureElement(MediaControls& mediaControls)
171     // Mapping onto same MediaControlElementType as panel element, since it has similar properties.
172     : MediaControlDivElement(mediaControls, MediaControlsPanel)
173 {
174 }
175
176 PassRefPtr<MediaControlOverlayEnclosureElement> MediaControlOverlayEnclosureElement::create(MediaControls& mediaControls)
177 {
178     return adoptRef(new MediaControlOverlayEnclosureElement(mediaControls));
179 }
180
181 const AtomicString& MediaControlOverlayEnclosureElement::shadowPseudoId() const
182 {
183     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-overlay-enclosure", AtomicString::ConstructFromLiteral));
184     return id;
185 }
186
187 // ----------------------------
188
189 MediaControlMuteButtonElement::MediaControlMuteButtonElement(MediaControls& mediaControls)
190     : MediaControlInputElement(mediaControls, MediaMuteButton)
191 {
192 }
193
194 PassRefPtr<MediaControlMuteButtonElement> MediaControlMuteButtonElement::create(MediaControls& mediaControls)
195 {
196     RefPtr<MediaControlMuteButtonElement> button = adoptRef(new MediaControlMuteButtonElement(mediaControls));
197     button->ensureUserAgentShadowRoot();
198     button->setType("button");
199     return button.release();
200 }
201
202 void MediaControlMuteButtonElement::defaultEventHandler(Event* event)
203 {
204     if (event->type() == EventTypeNames::click) {
205         mediaElement().setMuted(!mediaElement().muted());
206         event->setDefaultHandled();
207     }
208
209     HTMLInputElement::defaultEventHandler(event);
210 }
211
212 void MediaControlMuteButtonElement::updateDisplayType()
213 {
214     setDisplayType(mediaElement().muted() ? MediaUnMuteButton : MediaMuteButton);
215 }
216
217 const AtomicString& MediaControlMuteButtonElement::shadowPseudoId() const
218 {
219     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-mute-button", AtomicString::ConstructFromLiteral));
220     return id;
221 }
222
223 // ----------------------------
224
225 MediaControlPlayButtonElement::MediaControlPlayButtonElement(MediaControls& mediaControls)
226     : MediaControlInputElement(mediaControls, MediaPlayButton)
227 {
228 }
229
230 PassRefPtr<MediaControlPlayButtonElement> MediaControlPlayButtonElement::create(MediaControls& mediaControls)
231 {
232     RefPtr<MediaControlPlayButtonElement> button = adoptRef(new MediaControlPlayButtonElement(mediaControls));
233     button->ensureUserAgentShadowRoot();
234     button->setType("button");
235     return button.release();
236 }
237
238 void MediaControlPlayButtonElement::defaultEventHandler(Event* event)
239 {
240     if (event->type() == EventTypeNames::click) {
241         mediaElement().togglePlayState();
242         updateDisplayType();
243         event->setDefaultHandled();
244     }
245     HTMLInputElement::defaultEventHandler(event);
246 }
247
248 void MediaControlPlayButtonElement::updateDisplayType()
249 {
250     setDisplayType(mediaElement().togglePlayStateWillPlay() ? MediaPlayButton : MediaPauseButton);
251 }
252
253 const AtomicString& MediaControlPlayButtonElement::shadowPseudoId() const
254 {
255     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-play-button", AtomicString::ConstructFromLiteral));
256     return id;
257 }
258
259 // ----------------------------
260
261 MediaControlOverlayPlayButtonElement::MediaControlOverlayPlayButtonElement(MediaControls& mediaControls)
262     : MediaControlInputElement(mediaControls, MediaOverlayPlayButton)
263 {
264 }
265
266 PassRefPtr<MediaControlOverlayPlayButtonElement> MediaControlOverlayPlayButtonElement::create(MediaControls& mediaControls)
267 {
268     RefPtr<MediaControlOverlayPlayButtonElement> button = adoptRef(new MediaControlOverlayPlayButtonElement(mediaControls));
269     button->ensureUserAgentShadowRoot();
270     button->setType("button");
271     return button.release();
272 }
273
274 void MediaControlOverlayPlayButtonElement::defaultEventHandler(Event* event)
275 {
276     if (event->type() == EventTypeNames::click && mediaElement().togglePlayStateWillPlay()) {
277         mediaElement().togglePlayState();
278         updateDisplayType();
279         event->setDefaultHandled();
280     }
281 }
282
283 void MediaControlOverlayPlayButtonElement::updateDisplayType()
284 {
285     if (mediaElement().togglePlayStateWillPlay()) {
286         show();
287     } else
288         hide();
289 }
290
291 const AtomicString& MediaControlOverlayPlayButtonElement::shadowPseudoId() const
292 {
293     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-overlay-play-button", AtomicString::ConstructFromLiteral));
294     return id;
295 }
296
297
298 // ----------------------------
299
300 MediaControlToggleClosedCaptionsButtonElement::MediaControlToggleClosedCaptionsButtonElement(MediaControls& mediaControls)
301     : MediaControlInputElement(mediaControls, MediaShowClosedCaptionsButton)
302 {
303 }
304
305 PassRefPtr<MediaControlToggleClosedCaptionsButtonElement> MediaControlToggleClosedCaptionsButtonElement::create(MediaControls& mediaControls)
306 {
307     RefPtr<MediaControlToggleClosedCaptionsButtonElement> button = adoptRef(new MediaControlToggleClosedCaptionsButtonElement(mediaControls));
308     button->ensureUserAgentShadowRoot();
309     button->setType("button");
310     button->hide();
311     return button.release();
312 }
313
314 void MediaControlToggleClosedCaptionsButtonElement::updateDisplayType()
315 {
316     bool captionsVisible = mediaElement().closedCaptionsVisible();
317     setDisplayType(captionsVisible ? MediaHideClosedCaptionsButton : MediaShowClosedCaptionsButton);
318     setChecked(captionsVisible);
319 }
320
321 void MediaControlToggleClosedCaptionsButtonElement::defaultEventHandler(Event* event)
322 {
323     if (event->type() == EventTypeNames::click) {
324         mediaElement().setClosedCaptionsVisible(!mediaElement().closedCaptionsVisible());
325         setChecked(mediaElement().closedCaptionsVisible());
326         updateDisplayType();
327         event->setDefaultHandled();
328     }
329
330     HTMLInputElement::defaultEventHandler(event);
331 }
332
333 const AtomicString& MediaControlToggleClosedCaptionsButtonElement::shadowPseudoId() const
334 {
335     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-toggle-closed-captions-button", AtomicString::ConstructFromLiteral));
336     return id;
337 }
338
339 // ----------------------------
340
341 MediaControlTimelineElement::MediaControlTimelineElement(MediaControls& mediaControls)
342     : MediaControlInputElement(mediaControls, MediaSlider)
343 {
344 }
345
346 PassRefPtr<MediaControlTimelineElement> MediaControlTimelineElement::create(MediaControls& mediaControls)
347 {
348     RefPtr<MediaControlTimelineElement> timeline = adoptRef(new MediaControlTimelineElement(mediaControls));
349     timeline->ensureUserAgentShadowRoot();
350     timeline->setType("range");
351     timeline->setAttribute(stepAttr, "any");
352     return timeline.release();
353 }
354
355 void MediaControlTimelineElement::defaultEventHandler(Event* event)
356 {
357     if (event->isMouseEvent() && toMouseEvent(event)->button() != LeftButton)
358         return;
359
360     if (!inDocument() || !document().isActive())
361         return;
362
363     if (event->type() == EventTypeNames::mousedown)
364         mediaControls().beginScrubbing();
365
366     if (event->type() == EventTypeNames::mouseup)
367         mediaControls().endScrubbing();
368
369     MediaControlInputElement::defaultEventHandler(event);
370
371     if (event->type() == EventTypeNames::mouseover || event->type() == EventTypeNames::mouseout || event->type() == EventTypeNames::mousemove)
372         return;
373
374     double time = value().toDouble();
375     if (event->type() == EventTypeNames::input) {
376         // FIXME: This will need to take the timeline offset into consideration
377         // once that concept is supported, see https://crbug.com/312699
378         if (mediaElement().controller())
379             mediaElement().controller()->setCurrentTime(time, IGNORE_EXCEPTION);
380         else
381             mediaElement().setCurrentTime(time, IGNORE_EXCEPTION);
382     }
383
384     RenderSlider* slider = toRenderSlider(renderer());
385     if (slider && slider->inDragMode())
386         mediaControls().updateCurrentTimeDisplay();
387 }
388
389 bool MediaControlTimelineElement::willRespondToMouseClickEvents()
390 {
391     return inDocument() && document().isActive();
392 }
393
394 void MediaControlTimelineElement::setPosition(double currentTime)
395 {
396     setValue(String::number(currentTime));
397 }
398
399 void MediaControlTimelineElement::setDuration(double duration)
400 {
401     setFloatingPointAttribute(maxAttr, std::isfinite(duration) ? duration : 0);
402 }
403
404
405 const AtomicString& MediaControlTimelineElement::shadowPseudoId() const
406 {
407     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-timeline", AtomicString::ConstructFromLiteral));
408     return id;
409 }
410
411 // ----------------------------
412
413 MediaControlVolumeSliderElement::MediaControlVolumeSliderElement(MediaControls& mediaControls)
414     : MediaControlInputElement(mediaControls, MediaVolumeSlider)
415 {
416 }
417
418 PassRefPtr<MediaControlVolumeSliderElement> MediaControlVolumeSliderElement::create(MediaControls& mediaControls)
419 {
420     RefPtr<MediaControlVolumeSliderElement> slider = adoptRef(new MediaControlVolumeSliderElement(mediaControls));
421     slider->ensureUserAgentShadowRoot();
422     slider->setType("range");
423     slider->setAttribute(stepAttr, "any");
424     slider->setAttribute(maxAttr, "1");
425     return slider.release();
426 }
427
428 void MediaControlVolumeSliderElement::defaultEventHandler(Event* event)
429 {
430     if (event->isMouseEvent() && toMouseEvent(event)->button() != LeftButton)
431         return;
432
433     if (!inDocument() || !document().isActive())
434         return;
435
436     MediaControlInputElement::defaultEventHandler(event);
437
438     if (event->type() == EventTypeNames::mouseover || event->type() == EventTypeNames::mouseout || event->type() == EventTypeNames::mousemove)
439         return;
440
441     double volume = value().toDouble();
442     mediaElement().setVolume(volume, ASSERT_NO_EXCEPTION);
443     mediaElement().setMuted(false);
444 }
445
446 bool MediaControlVolumeSliderElement::willRespondToMouseMoveEvents()
447 {
448     if (!inDocument() || !document().isActive())
449         return false;
450
451     return MediaControlInputElement::willRespondToMouseMoveEvents();
452 }
453
454 bool MediaControlVolumeSliderElement::willRespondToMouseClickEvents()
455 {
456     if (!inDocument() || !document().isActive())
457         return false;
458
459     return MediaControlInputElement::willRespondToMouseClickEvents();
460 }
461
462 void MediaControlVolumeSliderElement::setVolume(double volume)
463 {
464     if (value().toDouble() != volume)
465         setValue(String::number(volume));
466 }
467
468 const AtomicString& MediaControlVolumeSliderElement::shadowPseudoId() const
469 {
470     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-volume-slider", AtomicString::ConstructFromLiteral));
471     return id;
472 }
473
474 // ----------------------------
475
476 MediaControlFullscreenButtonElement::MediaControlFullscreenButtonElement(MediaControls& mediaControls)
477     : MediaControlInputElement(mediaControls, MediaEnterFullscreenButton)
478 {
479 }
480
481 PassRefPtr<MediaControlFullscreenButtonElement> MediaControlFullscreenButtonElement::create(MediaControls& mediaControls)
482 {
483     RefPtr<MediaControlFullscreenButtonElement> button = adoptRef(new MediaControlFullscreenButtonElement(mediaControls));
484     button->ensureUserAgentShadowRoot();
485     button->setType("button");
486     button->hide();
487     return button.release();
488 }
489
490 void MediaControlFullscreenButtonElement::defaultEventHandler(Event* event)
491 {
492     if (event->type() == EventTypeNames::click) {
493         if (FullscreenElementStack::isActiveFullScreenElement(&mediaElement()))
494             FullscreenElementStack::from(document()).webkitCancelFullScreen();
495         else
496             FullscreenElementStack::from(document()).requestFullScreenForElement(&mediaElement(), 0, FullscreenElementStack::ExemptIFrameAllowFullScreenRequirement);
497         event->setDefaultHandled();
498     }
499     HTMLInputElement::defaultEventHandler(event);
500 }
501
502 const AtomicString& MediaControlFullscreenButtonElement::shadowPseudoId() const
503 {
504     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-fullscreen-button", AtomicString::ConstructFromLiteral));
505     return id;
506 }
507
508 void MediaControlFullscreenButtonElement::setIsFullscreen(bool isFullscreen)
509 {
510     setDisplayType(isFullscreen ? MediaExitFullscreenButton : MediaEnterFullscreenButton);
511 }
512
513 // ----------------------------
514
515 MediaControlTimeRemainingDisplayElement::MediaControlTimeRemainingDisplayElement(MediaControls& mediaControls)
516     : MediaControlTimeDisplayElement(mediaControls, MediaTimeRemainingDisplay)
517 {
518 }
519
520 PassRefPtr<MediaControlTimeRemainingDisplayElement> MediaControlTimeRemainingDisplayElement::create(MediaControls& mediaControls)
521 {
522     return adoptRef(new MediaControlTimeRemainingDisplayElement(mediaControls));
523 }
524
525 static const AtomicString& getMediaControlTimeRemainingDisplayElementShadowPseudoId()
526 {
527     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-time-remaining-display", AtomicString::ConstructFromLiteral));
528     return id;
529 }
530
531 const AtomicString& MediaControlTimeRemainingDisplayElement::shadowPseudoId() const
532 {
533     return getMediaControlTimeRemainingDisplayElementShadowPseudoId();
534 }
535
536 // ----------------------------
537
538 MediaControlCurrentTimeDisplayElement::MediaControlCurrentTimeDisplayElement(MediaControls& mediaControls)
539     : MediaControlTimeDisplayElement(mediaControls, MediaCurrentTimeDisplay)
540 {
541 }
542
543 PassRefPtr<MediaControlCurrentTimeDisplayElement> MediaControlCurrentTimeDisplayElement::create(MediaControls& mediaControls)
544 {
545     return adoptRef(new MediaControlCurrentTimeDisplayElement(mediaControls));
546 }
547
548 static const AtomicString& getMediaControlCurrentTimeDisplayElementShadowPseudoId()
549 {
550     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-controls-current-time-display", AtomicString::ConstructFromLiteral));
551     return id;
552 }
553
554 const AtomicString& MediaControlCurrentTimeDisplayElement::shadowPseudoId() const
555 {
556     return getMediaControlCurrentTimeDisplayElementShadowPseudoId();
557 }
558
559 // ----------------------------
560
561 MediaControlTextTrackContainerElement::MediaControlTextTrackContainerElement(MediaControls& mediaControls)
562     : MediaControlDivElement(mediaControls, MediaTextTrackDisplayContainer)
563     , m_fontSize(0)
564 {
565 }
566
567 PassRefPtr<MediaControlTextTrackContainerElement> MediaControlTextTrackContainerElement::create(MediaControls& mediaControls)
568 {
569     RefPtr<MediaControlTextTrackContainerElement> element = adoptRef(new MediaControlTextTrackContainerElement(mediaControls));
570     element->hide();
571     return element.release();
572 }
573
574 RenderObject* MediaControlTextTrackContainerElement::createRenderer(RenderStyle*)
575 {
576     return new RenderTextTrackContainerElement(this);
577 }
578
579 const AtomicString& MediaControlTextTrackContainerElement::textTrackContainerElementShadowPseudoId()
580 {
581     DEFINE_STATIC_LOCAL(AtomicString, id, ("-webkit-media-text-track-container", AtomicString::ConstructFromLiteral));
582     return id;
583 }
584
585 const AtomicString& MediaControlTextTrackContainerElement::shadowPseudoId() const
586 {
587     return textTrackContainerElementShadowPseudoId();
588 }
589
590 void MediaControlTextTrackContainerElement::updateDisplay()
591 {
592     if (!mediaElement().closedCaptionsVisible()) {
593         removeChildren();
594         return;
595     }
596
597     // 1. If the media element is an audio element, or is another playback
598     // mechanism with no rendering area, abort these steps. There is nothing to
599     // render.
600     if (isHTMLAudioElement(mediaElement()))
601         return;
602
603     // 2. Let video be the media element or other playback mechanism.
604     HTMLVideoElement& video = toHTMLVideoElement(mediaElement());
605
606     // 3. Let output be an empty list of absolutely positioned CSS block boxes.
607     Vector<RefPtr<HTMLDivElement> > output;
608
609     // 4. If the user agent is exposing a user interface for video, add to
610     // output one or more completely transparent positioned CSS block boxes that
611     // cover the same region as the user interface.
612
613     // 5. If the last time these rules were run, the user agent was not exposing
614     // a user interface for video, but now it is, let reset be true. Otherwise,
615     // let reset be false.
616
617     // There is nothing to be done explicitly for 4th and 5th steps, as
618     // everything is handled through CSS. The caption box is on top of the
619     // controls box, in a container set with the -webkit-box display property.
620
621     // 6. Let tracks be the subset of video's list of text tracks that have as
622     // their rules for updating the text track rendering these rules for
623     // updating the display of WebVTT text tracks, and whose text track mode is
624     // showing or showing by default.
625     // 7. Let cues be an empty list of text track cues.
626     // 8. For each track track in tracks, append to cues all the cues from
627     // track's list of cues that have their text track cue active flag set.
628     CueList activeCues = video.currentlyActiveCues();
629
630     // 9. If reset is false, then, for each text track cue cue in cues: if cue's
631     // text track cue display state has a set of CSS boxes, then add those boxes
632     // to output, and remove cue from cues.
633
634     // There is nothing explicitly to be done here, as all the caching occurs
635     // within the TextTrackCue instance itself. If parameters of the cue change,
636     // the display tree is cleared.
637
638     // 10. For each text track cue cue in cues that has not yet had
639     // corresponding CSS boxes added to output, in text track cue order, run the
640     // following substeps:
641     for (size_t i = 0; i < activeCues.size(); ++i) {
642         TextTrackCue* cue = activeCues[i].data();
643
644         ASSERT(cue->isActive());
645         if (!cue->track() || !cue->track()->isRendered() || !cue->isActive())
646             continue;
647
648         cue->updateDisplay(m_videoDisplaySize.size(), *this);
649     }
650
651     // 11. Return output.
652     if (hasChildren())
653         show();
654     else
655         hide();
656 }
657
658 void MediaControlTextTrackContainerElement::updateSizes()
659 {
660     if (!document().isActive())
661         return;
662
663     IntRect videoBox;
664
665     if (!mediaElement().renderer() || !mediaElement().renderer()->isVideo())
666         return;
667     videoBox = toRenderVideo(mediaElement().renderer())->videoBox();
668
669     if (m_videoDisplaySize == videoBox)
670         return;
671     m_videoDisplaySize = videoBox;
672
673     float smallestDimension = std::min(m_videoDisplaySize.size().height(), m_videoDisplaySize.size().width());
674
675     float fontSize = smallestDimension * 0.05f;
676     if (fontSize != m_fontSize) {
677         m_fontSize = fontSize;
678         setInlineStyleProperty(CSSPropertyFontSize, fontSize, CSSPrimitiveValue::CSS_PX);
679     }
680 }
681
682 // ----------------------------
683
684 } // namespace WebCore