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