2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef HTMLMediaElement_h
27 #define HTMLMediaElement_h
29 #include "core/dom/ActiveDOMObject.h"
30 #include "core/events/GenericEventQueue.h"
31 #include "core/html/HTMLElement.h"
32 #include "core/html/MediaControllerInterface.h"
33 #include "core/html/track/TextTrack.h"
34 #include "core/html/track/TextTrackCue.h"
35 #include "core/html/track/vtt/VTTCue.h"
36 #include "platform/PODIntervalTree.h"
37 #include "platform/graphics/media/MediaPlayer.h"
38 #include "public/platform/WebMimeRegistry.h"
41 class WebContentDecryptionModule;
42 class WebInbandTextTrack;
49 class AudioSourceProvider;
50 class MediaElementAudioSourceNode;
55 class HTMLSourceElement;
56 class HTMLTrackElement;
58 class MediaController;
62 class HTMLMediaSource;
66 typedef PODIntervalTree<double, TextTrackCue*> CueIntervalTree;
67 typedef CueIntervalTree::IntervalType CueInterval;
68 typedef Vector<CueInterval> CueList;
70 // FIXME: The inheritance from MediaPlayerClient here should be private inheritance.
71 // But it can't be until the Chromium WebMediaPlayerClientImpl class is fixed so it
72 // no longer depends on typecasting a MediaPlayerClient to an HTMLMediaElement.
74 class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, public ActiveDOMObject, public MediaControllerInterface
75 , private TextTrackClient
78 static blink::WebMimeRegistry::SupportsType supportsType(const ContentType&, const String& keySystem = String());
80 MediaPlayer* player() const { return m_player.get(); }
82 virtual bool isVideo() const = 0;
83 virtual bool hasVideo() const OVERRIDE { return false; }
84 virtual bool hasAudio() const OVERRIDE FINAL;
86 bool supportsSave() const;
88 blink::WebLayer* platformLayer() const;
90 enum DelayedActionType {
91 LoadMediaResource = 1 << 0,
92 LoadTextTrackResource = 1 << 1,
93 TextTrackChangesNotification = 1 << 2
95 void scheduleDelayedAction(DelayedActionType);
97 bool isActive() const { return m_active; }
100 PassRefPtr<MediaError> error() const;
103 void setSrc(const AtomicString&);
104 const KURL& currentSrc() const { return m_currentSrc; }
106 enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_NO_SOURCE };
107 NetworkState networkState() const;
109 String preload() const;
110 void setPreload(const AtomicString&);
112 virtual PassRefPtr<TimeRanges> buffered() const OVERRIDE FINAL;
114 String canPlayType(const String& mimeType, const String& keySystem = String()) const;
117 virtual ReadyState readyState() const OVERRIDE FINAL;
118 bool seeking() const;
121 virtual double currentTime() const OVERRIDE FINAL;
122 virtual void setCurrentTime(double, ExceptionState&) OVERRIDE FINAL;
123 virtual double duration() const OVERRIDE FINAL;
124 virtual bool paused() const OVERRIDE FINAL;
125 virtual double defaultPlaybackRate() const OVERRIDE FINAL;
126 virtual void setDefaultPlaybackRate(double) OVERRIDE FINAL;
127 virtual double playbackRate() const OVERRIDE FINAL;
128 virtual void setPlaybackRate(double) OVERRIDE FINAL;
129 void updatePlaybackRate();
130 virtual PassRefPtr<TimeRanges> played() OVERRIDE FINAL;
131 virtual PassRefPtr<TimeRanges> seekable() const OVERRIDE FINAL;
133 bool autoplay() const;
135 void setLoop(bool b);
136 virtual void play() OVERRIDE FINAL;
137 virtual void pause() OVERRIDE FINAL;
140 unsigned webkitAudioDecodedByteCount() const;
141 unsigned webkitVideoDecodedByteCount() const;
143 // media source extensions
144 void closeMediaSource();
145 void durationChanged(double duration);
147 // encrypted media extensions (v0.1b)
148 void webkitGenerateKeyRequest(const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState&);
149 void webkitGenerateKeyRequest(const String& keySystem, ExceptionState&);
150 void webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState&);
151 void webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionState&);
152 void webkitCancelKeyRequest(const String& keySystem, const String& sessionId, ExceptionState&);
154 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeyadded);
155 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeyerror);
156 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeymessage);
157 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitneedkey);
159 // encrypted media extensions (WD)
160 MediaKeys* mediaKeys() const { return m_mediaKeys.get(); }
161 void setMediaKeys(MediaKeys*, ExceptionState&);
162 DEFINE_ATTRIBUTE_EVENT_LISTENER(needkey);
165 bool controls() const;
166 void setControls(bool);
167 virtual double volume() const OVERRIDE FINAL;
168 virtual void setVolume(double, ExceptionState&) OVERRIDE FINAL;
169 virtual bool muted() const OVERRIDE FINAL;
170 virtual void setMuted(bool) OVERRIDE FINAL;
172 void togglePlayState();
173 virtual void beginScrubbing() OVERRIDE FINAL;
174 virtual void endScrubbing() OVERRIDE FINAL;
176 virtual bool canPlay() const OVERRIDE FINAL;
178 double percentLoaded() const;
180 PassRefPtr<TextTrack> addTextTrack(const AtomicString& kind, const AtomicString& label, const AtomicString& language, ExceptionState&);
181 PassRefPtr<TextTrack> addTextTrack(const AtomicString& kind, const AtomicString& label, ExceptionState& exceptionState) { return addTextTrack(kind, label, emptyAtom, exceptionState); }
182 PassRefPtr<TextTrack> addTextTrack(const AtomicString& kind, ExceptionState& exceptionState) { return addTextTrack(kind, emptyAtom, emptyAtom, exceptionState); }
184 TextTrackList* textTracks();
185 CueList currentlyActiveCues() const { return m_currentlyActiveCues; }
187 void addTrack(TextTrack*);
188 void removeTrack(TextTrack*);
189 void removeAllInbandTracks();
190 void closeCaptionTracksChanged();
191 void notifyMediaPlayerOfTextTrackChanges();
193 void didAddTrack(HTMLTrackElement*);
194 void didRemoveTrack(HTMLTrackElement*);
196 virtual void mediaPlayerDidAddTrack(blink::WebInbandTextTrack*) OVERRIDE FINAL;
197 virtual void mediaPlayerDidRemoveTrack(blink::WebInbandTextTrack*) OVERRIDE FINAL;
200 enum GroupKind { CaptionsAndSubtitles, Description, Chapter, Metadata, Other };
202 TrackGroup(GroupKind kind)
210 Vector<RefPtr<TextTrack> > tracks;
211 RefPtr<TextTrack> visibleTrack;
212 RefPtr<TextTrack> defaultTrack;
217 void configureTextTrackGroupForLanguage(const TrackGroup&) const;
218 void configureTextTracks();
219 void configureTextTrackGroup(const TrackGroup&);
221 bool textTracksAreReady() const;
222 enum VisibilityChangeAssumption {
223 AssumeNoVisibleChange,
226 void configureTextTrackDisplay(VisibilityChangeAssumption);
227 void updateTextTrackDisplay();
228 void textTrackReadyStateChanged(TextTrack*);
231 virtual void textTrackKindChanged(TextTrack*) OVERRIDE FINAL;
232 virtual void textTrackModeChanged(TextTrack*) OVERRIDE FINAL;
233 virtual void textTrackAddCues(TextTrack*, const TextTrackCueList*) OVERRIDE FINAL;
234 virtual void textTrackRemoveCues(TextTrack*, const TextTrackCueList*) OVERRIDE FINAL;
235 virtual void textTrackAddCue(TextTrack*, PassRefPtr<TextTrackCue>) OVERRIDE FINAL;
236 virtual void textTrackRemoveCue(TextTrack*, PassRefPtr<TextTrackCue>) OVERRIDE FINAL;
238 // EventTarget function.
239 // Both Node (via HTMLElement) and ActiveDOMObject define this method, which
240 // causes an ambiguity error at compile time. This class's constructor
241 // ensures that both implementations return document, so return the result
242 // of one of them here.
243 virtual ExecutionContext* executionContext() const OVERRIDE FINAL { return HTMLElement::executionContext(); }
245 bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
247 virtual bool isFullscreen() const OVERRIDE FINAL;
248 virtual void enterFullscreen() OVERRIDE FINAL;
249 void exitFullscreen();
251 virtual bool hasClosedCaptions() const OVERRIDE FINAL;
252 virtual bool closedCaptionsVisible() const OVERRIDE FINAL;
253 virtual void setClosedCaptionsVisible(bool) OVERRIDE FINAL;
255 MediaControls* mediaControls() const;
257 void sourceWasRemoved(HTMLSourceElement*);
258 void sourceWasAdded(HTMLSourceElement*);
260 bool isPlaying() const { return m_playing; }
262 // ActiveDOMObject functions.
263 virtual bool hasPendingActivity() const OVERRIDE FINAL;
264 virtual void contextDestroyed() OVERRIDE FINAL;
266 #if ENABLE(WEB_AUDIO)
267 MediaElementAudioSourceNode* audioSourceNode() { return m_audioSourceNode; }
268 void setAudioSourceNode(MediaElementAudioSourceNode*);
270 AudioSourceProvider* audioSourceProvider();
273 enum InvalidURLAction { DoNothing, Complain };
274 bool isSafeToLoadURL(const KURL&, InvalidURLAction);
276 MediaController* controller() const;
277 void setController(PassRefPtr<MediaController>); // Resets the MediaGroup and sets the MediaController.
280 HTMLMediaElement(const QualifiedName&, Document&, bool);
281 virtual ~HTMLMediaElement();
283 virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE;
284 virtual void finishParsingChildren() OVERRIDE FINAL;
285 virtual bool isURLAttribute(const Attribute&) const OVERRIDE;
286 virtual void attach(const AttachContext& = AttachContext()) OVERRIDE;
288 virtual void didMoveToNewDocument(Document& oldDocument) OVERRIDE;
290 enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video };
291 DisplayMode displayMode() const { return m_displayMode; }
292 virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; }
294 virtual bool isMediaElement() const OVERRIDE FINAL { return true; }
296 void setControllerInternal(PassRefPtr<MediaController>);
298 // Restrictions to change default behaviors.
299 enum BehaviorRestrictionFlags {
301 RequireUserGestureForLoadRestriction = 1 << 0,
302 RequireUserGestureForRateChangeRestriction = 1 << 1,
303 RequireUserGestureForFullscreenRestriction = 1 << 2,
304 RequirePageConsentToLoadMediaRestriction = 1 << 3,
306 typedef unsigned BehaviorRestrictions;
308 bool userGestureRequiredForLoad() const { return m_restrictions & RequireUserGestureForLoadRestriction; }
309 bool userGestureRequiredForRateChange() const { return m_restrictions & RequireUserGestureForRateChangeRestriction; }
310 bool userGestureRequiredForFullscreen() const { return m_restrictions & RequireUserGestureForFullscreenRestriction; }
311 bool pageConsentRequiredForLoad() const { return m_restrictions & RequirePageConsentToLoadMediaRestriction; }
313 void addBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions |= restriction; }
314 void removeBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions &= ~restriction; }
316 bool ignoreTrackDisplayUpdateRequests() const { return m_ignoreTrackDisplayUpdate > 0; }
317 void beginIgnoringTrackDisplayUpdateRequests();
318 void endIgnoringTrackDisplayUpdateRequests();
321 void createMediaPlayer();
323 virtual bool alwaysCreateUserAgentShadowRoot() const OVERRIDE FINAL { return true; }
324 virtual bool areAuthorShadowsAllowed() const OVERRIDE FINAL { return false; }
326 virtual bool hasCustomFocusLogic() const OVERRIDE FINAL;
327 virtual bool supportsFocus() const OVERRIDE FINAL;
328 virtual bool isMouseFocusable() const OVERRIDE FINAL;
329 virtual bool rendererIsNeeded(const RenderStyle&) OVERRIDE;
330 virtual RenderObject* createRenderer(RenderStyle*) OVERRIDE;
331 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE FINAL;
332 virtual void removedFrom(ContainerNode*) OVERRIDE FINAL;
333 virtual void didRecalcStyle(StyleRecalcChange) OVERRIDE FINAL;
335 virtual void didBecomeFullscreenElement() OVERRIDE FINAL;
336 virtual void willStopBeingFullscreenElement() OVERRIDE FINAL;
337 virtual bool isInteractiveContent() const OVERRIDE FINAL;
339 // ActiveDOMObject functions.
340 virtual void stop() OVERRIDE FINAL;
342 virtual void updateDisplayState() { }
344 void setReadyState(MediaPlayer::ReadyState);
345 void setNetworkState(MediaPlayer::NetworkState);
347 virtual void mediaPlayerNetworkStateChanged() OVERRIDE FINAL;
348 virtual void mediaPlayerReadyStateChanged() OVERRIDE FINAL;
349 virtual void mediaPlayerTimeChanged() OVERRIDE FINAL;
350 virtual void mediaPlayerDurationChanged() OVERRIDE FINAL;
351 virtual void mediaPlayerPlaybackStateChanged() OVERRIDE FINAL;
352 virtual void mediaPlayerRequestFullscreen() OVERRIDE FINAL;
353 virtual void mediaPlayerRequestSeek(double) OVERRIDE FINAL;
354 virtual void mediaPlayerRepaint() OVERRIDE FINAL;
355 virtual void mediaPlayerSizeChanged() OVERRIDE FINAL;
357 virtual void mediaPlayerKeyAdded(const String& keySystem, const String& sessionId) OVERRIDE FINAL;
358 virtual void mediaPlayerKeyError(const String& keySystem, const String& sessionId, MediaPlayerClient::MediaKeyErrorCode, unsigned short systemCode) OVERRIDE FINAL;
359 virtual void mediaPlayerKeyMessage(const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength, const KURL& defaultURL) OVERRIDE FINAL;
360 virtual bool mediaPlayerKeyNeeded(const String& contentType, const unsigned char* initData, unsigned initDataLength) OVERRIDE FINAL;
362 virtual CORSMode mediaPlayerCORSMode() const OVERRIDE FINAL;
364 virtual void mediaPlayerSetWebLayer(blink::WebLayer*) OVERRIDE FINAL;
365 virtual void mediaPlayerSetOpaque(bool) OVERRIDE FINAL;
366 virtual void mediaPlayerMediaSourceOpened(blink::WebMediaSource*) OVERRIDE FINAL;
368 void loadTimerFired(Timer<HTMLMediaElement>*);
369 void progressEventTimerFired(Timer<HTMLMediaElement>*);
370 void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
371 void startPlaybackProgressTimer();
372 void startProgressEventTimer();
373 void stopPeriodicTimers();
375 void seek(double time, ExceptionState&);
377 void checkIfSeekNeeded();
378 void addPlayedRange(double start, double end);
380 void scheduleTimeupdateEvent(bool periodicEvent);
381 void scheduleEvent(const AtomicString& eventName);
384 void selectMediaResource();
385 void loadResource(const KURL&, ContentType&, const String& keySystem);
386 void scheduleNextSourceChild();
387 void loadNextSourceChild();
388 void userCancelledLoad();
389 void clearMediaPlayer(int flags);
390 void clearMediaPlayerAndAudioSourceProviderClient();
391 bool havePotentialSourceChild();
392 void noneSupported();
393 void mediaEngineError(PassRefPtr<MediaError> err);
394 void cancelPendingEventsAndCallbacks();
395 void waitForSourceChange();
396 void prepareToPlay();
398 KURL selectNextSourceChild(ContentType*, String* keySystem, InvalidURLAction);
400 void mediaLoadingFailed(MediaPlayer::NetworkState);
402 void updateActiveTextTrackCues(double);
403 HTMLTrackElement* showingTrackWithSameKind(HTMLTrackElement*) const;
405 void markCaptionAndSubtitleTracksAsUnconfigured();
407 // These "internal" functions do not check user gesture restrictions.
410 void pauseInternal();
412 void prepareForLoad();
413 void allowVideoRendering();
416 void updatePlayState();
417 bool potentiallyPlaying() const;
418 bool endedPlayback() const;
419 bool stoppedDueToErrors() const;
420 bool pausedForUserInteraction() const;
421 bool couldPlayIfEnoughData() const;
423 // Pauses playback without changing any states or generating events
424 void setPausedInternal(bool);
426 void setPlaybackRateInternal(double);
428 void setShouldDelayLoadEvent(bool);
429 void invalidateCachedTime();
430 void refreshCachedTime() const;
432 bool hasMediaControls() const;
433 bool createMediaControls();
434 void configureMediaControls();
436 void prepareMediaFragmentURI();
437 void applyMediaFragmentURI();
439 virtual void* preDispatchEventHandler(Event*) OVERRIDE FINAL;
441 void changeNetworkStateFromLoadingToIdle();
443 void removeBehaviorsRestrictionsAfterFirstUserGesture();
445 const AtomicString& mediaGroup() const;
446 void setMediaGroup(const AtomicString&);
447 void updateMediaController();
448 bool isBlocked() const;
449 bool isBlockedOnMediaController() const;
450 virtual bool hasCurrentSrc() const OVERRIDE FINAL { return !m_currentSrc.isEmpty(); }
451 bool isAutoplaying() const { return m_autoplaying; }
453 // Currently we have both EME v0.1b and EME WD implemented in media element.
454 // But we do not want to support both at the same time. The one used first
455 // will be supported. Use |m_emeMode| to track this selection.
456 // FIXME: Remove EmeMode once EME v0.1b support is removed. See crbug.com/249976.
457 enum EmeMode { EmeModeNotSelected, EmeModePrefixed, EmeModeUnprefixed };
459 // check (and set if necessary) the encrypted media extensions (EME) mode
460 // (v0.1b or WD). Returns whether the mode is allowed and successfully set.
461 bool setEmeMode(EmeMode, ExceptionState&);
463 blink::WebContentDecryptionModule* contentDecryptionModule();
464 void setMediaKeysInternal(MediaKeys*);
466 Timer<HTMLMediaElement> m_loadTimer;
467 Timer<HTMLMediaElement> m_progressEventTimer;
468 Timer<HTMLMediaElement> m_playbackProgressTimer;
469 RefPtr<TimeRanges> m_playedTimeRanges;
470 OwnPtr<GenericEventQueue> m_asyncEventQueue;
472 double m_playbackRate;
473 double m_defaultPlaybackRate;
474 NetworkState m_networkState;
475 ReadyState m_readyState;
476 ReadyState m_readyStateMaximum;
479 RefPtr<MediaError> m_error;
482 double m_lastSeekTime;
484 double m_previousProgressTime;
486 // Cached duration to suppress duplicate events if duration unchanged.
489 // The last time a timeupdate event was sent (wall clock).
490 double m_lastTimeUpdateEventWallTime;
492 // The last time a timeupdate event was sent in movie time.
493 double m_lastTimeUpdateEventMovieTime;
496 enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
497 LoadState m_loadState;
498 RefPtr<HTMLSourceElement> m_currentSourceNode;
499 RefPtr<Node> m_nextChildNodeToConsider;
501 OwnPtr<MediaPlayer> m_player;
502 blink::WebLayer* m_webLayer;
505 BehaviorRestrictions m_restrictions;
507 MediaPlayer::Preload m_preload;
509 DisplayMode m_displayMode;
511 RefPtr<HTMLMediaSource> m_mediaSource;
513 mutable double m_cachedTime;
514 mutable double m_cachedTimeWallClockUpdateTime;
515 mutable double m_minimumWallClockTimeToCacheMediaTime;
517 double m_fragmentStartTime;
518 double m_fragmentEndTime;
520 typedef unsigned PendingActionFlags;
521 PendingActionFlags m_pendingActionFlags;
523 // FIXME: MediaElement has way too many state bits.
525 bool m_shouldDelayLoadEvent : 1;
526 bool m_haveFiredLoadedData : 1;
528 bool m_autoplaying : 1;
533 // data has not been loaded since sending a "stalled" event
534 bool m_sentStalledEvent : 1;
536 // time has not changed since sending an "ended" event
537 bool m_sentEndEvent : 1;
539 bool m_pausedInternal : 1;
541 bool m_closedCaptionsVisible : 1;
543 bool m_loadInitiatedByUserGesture : 1;
544 bool m_completelyLoaded : 1;
545 bool m_havePreparedToPlay : 1;
546 bool m_parsingInProgress : 1;
548 bool m_tracksAreReady : 1;
549 bool m_haveVisibleTextTrack : 1;
550 bool m_processingPreferenceChange : 1;
551 double m_lastTextTrackUpdateTime;
553 RefPtr<TextTrackList> m_textTracks;
554 Vector<RefPtr<TextTrack> > m_textTracksWhenResourceSelectionBegan;
556 CueIntervalTree m_cueTree;
558 CueList m_currentlyActiveCues;
559 int m_ignoreTrackDisplayUpdate;
561 #if ENABLE(WEB_AUDIO)
562 // This is a weak reference, since m_audioSourceNode holds a reference to us.
563 // The value is set just after the MediaElementAudioSourceNode is created.
564 // The value is cleared in MediaElementAudioSourceNode::~MediaElementAudioSourceNode().
565 MediaElementAudioSourceNode* m_audioSourceNode;
568 friend class MediaController;
569 RefPtr<MediaController> m_mediaController;
571 friend class TrackDisplayUpdateScope;
575 RefPtr<MediaKeys> m_mediaKeys;
579 // Template specializations required by PodIntervalTree in debug mode.
581 struct ValueToString<double> {
582 static String string(const double value)
584 return String::number(value);
589 struct ValueToString<TextTrackCue*> {
590 static String string(TextTrackCue* const& cue)
592 return cue->toString();
597 inline bool isHTMLMediaElement(const Node& node)
599 return node.isElementNode() && toElement(node).isMediaElement();
602 DEFINE_NODE_TYPE_CASTS_WITH_FUNCTION(HTMLMediaElement);