[EME] Add basic implementation of HTMLMediaElement::setMediaKeys()
[WebKit-https.git] / Source / WebCore / html / HTMLMediaElement.h
1 /*
2  * Copyright (C) 2007-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE 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 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.
24  */
25
26 #pragma once
27
28 #if ENABLE(VIDEO)
29
30 #include "ActiveDOMObject.h"
31 #include "AutoplayEvent.h"
32 #include "GenericEventQueue.h"
33 #include "GenericTaskQueue.h"
34 #include "HTMLElement.h"
35 #include "HTMLMediaElementEnums.h"
36 #include "MediaCanStartListener.h"
37 #include "MediaControllerInterface.h"
38 #include "MediaElementSession.h"
39 #include "MediaProducer.h"
40 #include "VisibilityChangeClient.h"
41 #include <wtf/Function.h>
42 #include <wtf/WeakPtr.h>
43
44 #if ENABLE(VIDEO_TRACK)
45 #include "AudioTrack.h"
46 #include "CaptionUserPreferences.h"
47 #include "PODIntervalTree.h"
48 #include "TextTrack.h"
49 #include "TextTrackCue.h"
50 #include "VTTCue.h"
51 #include "VideoTrack.h"
52 #endif
53
54 #if USE(AUDIO_SESSION) && PLATFORM(MAC)
55 #include "AudioSession.h"
56 #endif
57
58 #if ENABLE(ENCRYPTED_MEDIA)
59 #include "CDMClient.h"
60 #endif
61
62 #ifndef NDEBUG
63 #include <wtf/StringPrintStream.h>
64 #endif
65
66 namespace PAL {
67 class SleepDisabler;
68 }
69
70 namespace WebCore {
71
72 class AudioSourceProvider;
73 class AudioTrackList;
74 class AudioTrackPrivate;
75 class Blob;
76 class DOMError;
77 class DeferredPromise;
78 class Event;
79 class HTMLSourceElement;
80 class HTMLTrackElement;
81 class InbandTextTrackPrivate;
82 class MediaController;
83 class MediaControls;
84 class MediaControlsHost;
85 class MediaElementAudioSourceNode;
86 class MediaError;
87 class MediaKeys;
88 class MediaPlayer;
89 class MediaResourceLoader;
90 class MediaSession;
91 class MediaSource;
92 class MediaStream;
93 class RenderMedia;
94 class ScriptExecutionContext;
95 class SourceBuffer;
96 class TextTrackList;
97 class TimeRanges;
98 class VideoPlaybackQuality;
99 class VideoTrackList;
100 class VideoTrackPrivate;
101 class WebKitMediaKeys;
102
103 template<typename> class DOMPromiseDeferred;
104
105 #if ENABLE(VIDEO_TRACK)
106 using CueIntervalTree = PODIntervalTree<MediaTime, TextTrackCue*>;
107 using CueInterval = CueIntervalTree::IntervalType;
108 using CueList = Vector<CueInterval>;
109 #endif
110
111 using MediaProvider = std::optional<Variant<
112 #if ENABLE(MEDIA_STREAM)
113     RefPtr<MediaStream>,
114 #endif
115 #if ENABLE(MEDIA_SOURCE)
116     RefPtr<MediaSource>,
117 #endif
118     RefPtr<Blob>>>;
119
120 class HTMLMediaElement
121     : public HTMLElement
122     , public ActiveDOMObject
123     , public MediaControllerInterface
124     , public MediaPlayerSupportsTypeClient
125     , public PlatformMediaSessionClient
126     , private MediaCanStartListener
127     , private MediaPlayerClient
128     , private MediaProducer
129     , private VisibilityChangeClient
130 #if ENABLE(VIDEO_TRACK)
131     , private AudioTrackClient
132     , private TextTrackClient
133     , private VideoTrackClient
134 #endif
135 #if USE(AUDIO_SESSION) && PLATFORM(MAC)
136     , private AudioSession::MutedStateObserver
137 #endif
138 #if ENABLE(ENCRYPTED_MEDIA)
139     , private CDMClient
140 #endif
141 {
142 public:
143     WeakPtr<HTMLMediaElement> createWeakPtr() { return m_weakFactory.createWeakPtr(); }
144     MediaPlayer* player() const { return m_player.get(); }
145
146     virtual bool isVideo() const { return false; }
147     bool hasVideo() const override { return false; }
148     bool hasAudio() const override;
149
150     static HashSet<HTMLMediaElement*>& allMediaElements();
151
152     static HTMLMediaElement* bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose);
153
154     void rewind(double timeDelta);
155     WEBCORE_EXPORT void returnToRealtime() override;
156
157     // Eventually overloaded in HTMLVideoElement
158     bool supportsFullscreen(HTMLMediaElementEnums::VideoFullscreenMode) const override { return false; };
159
160     bool supportsScanning() const override;
161
162     bool canSaveMediaData() const;
163
164     bool doesHaveAttribute(const AtomicString&, AtomicString* value = nullptr) const override;
165
166     WEBCORE_EXPORT PlatformMedia platformMedia() const;
167     PlatformLayer* platformLayer() const;
168     bool isVideoLayerInline();
169     void setPreparedToReturnVideoLayerToInline(bool);
170     void waitForPreparedForInlineThen(WTF::Function<void()>&& completionHandler = [] { });
171 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
172     void setVideoFullscreenLayer(PlatformLayer*, WTF::Function<void()>&& completionHandler = [] { });
173     PlatformLayer* videoFullscreenLayer() const { return m_videoFullscreenLayer.get(); }
174     void setVideoFullscreenFrame(FloatRect);
175     void setVideoFullscreenGravity(MediaPlayerEnums::VideoGravity);
176     MediaPlayerEnums::VideoGravity videoFullscreenGravity() const { return m_videoFullscreenGravity; }
177 #endif
178
179     using HTMLMediaElementEnums::DelayedActionType;
180     void scheduleDelayedAction(DelayedActionType);
181     void scheduleResolvePendingPlayPromises();
182     void rejectPendingPlayPromises(DOMError&);
183     void resolvePendingPlayPromises();
184     void scheduleNotifyAboutPlaying();
185     void notifyAboutPlaying();
186     
187     MediaPlayerEnums::MovieLoadType movieLoadType() const;
188     
189     bool inActiveDocument() const { return m_inActiveDocument; }
190
191     const Document* hostingDocument() const override { return &document(); }
192
193 // DOM API
194 // error state
195     WEBCORE_EXPORT MediaError* error() const;
196
197     const URL& currentSrc() const { return m_currentSrc; }
198
199     const MediaProvider& srcObject() const { return m_mediaProvider; }
200     void setSrcObject(MediaProvider&&);
201
202     WEBCORE_EXPORT void setCrossOrigin(const AtomicString&);
203     WEBCORE_EXPORT String crossOrigin() const;
204
205 // network state
206     using HTMLMediaElementEnums::NetworkState;
207     WEBCORE_EXPORT NetworkState networkState() const;
208
209     WEBCORE_EXPORT String preload() const;
210     WEBCORE_EXPORT void setPreload(const String&);
211
212     Ref<TimeRanges> buffered() const override;
213     WEBCORE_EXPORT void load();
214     WEBCORE_EXPORT String canPlayType(const String& mimeType) const;
215
216 // ready state
217     using HTMLMediaElementEnums::ReadyState;
218     ReadyState readyState() const override;
219     WEBCORE_EXPORT bool seeking() const;
220
221 // playback state
222     WEBCORE_EXPORT double currentTime() const override;
223     void setCurrentTime(double) override;
224     double currentTimeForBindings() const { return currentTime(); }
225     WEBCORE_EXPORT ExceptionOr<void> setCurrentTimeForBindings(double);
226     WEBCORE_EXPORT double getStartDate() const;
227     WEBCORE_EXPORT double duration() const override;
228     WEBCORE_EXPORT bool paused() const override;
229     double defaultPlaybackRate() const override;
230     void setDefaultPlaybackRate(double) override;
231     WEBCORE_EXPORT double playbackRate() const override;
232     void setPlaybackRate(double) override;
233
234 // MediaTime versions of playback state
235     MediaTime currentMediaTime() const;
236     void setCurrentTime(const MediaTime&);
237     MediaTime durationMediaTime() const;
238     WEBCORE_EXPORT void fastSeek(const MediaTime&);
239
240     void updatePlaybackRate();
241     WEBCORE_EXPORT bool webkitPreservesPitch() const;
242     WEBCORE_EXPORT void setWebkitPreservesPitch(bool);
243     Ref<TimeRanges> played() override;
244     Ref<TimeRanges> seekable() const override;
245     double seekableTimeRangesLastModifiedTime() const;
246     double liveUpdateInterval() const;
247     WEBCORE_EXPORT bool ended() const;
248     bool autoplay() const;
249     bool isAutoplaying() const { return m_autoplaying; }
250     bool loop() const;
251     void setLoop(bool b);
252
253     void play(DOMPromiseDeferred<void>&&);
254
255     WEBCORE_EXPORT void play() override;
256     WEBCORE_EXPORT void pause() override;
257     void setShouldBufferData(bool) override;
258     WEBCORE_EXPORT void fastSeek(double);
259     double minFastReverseRate() const;
260     double maxFastForwardRate() const;
261
262     void purgeBufferedDataIfPossible();
263
264 // captions
265     WEBCORE_EXPORT bool webkitHasClosedCaptions() const;
266     WEBCORE_EXPORT bool webkitClosedCaptionsVisible() const;
267     WEBCORE_EXPORT void setWebkitClosedCaptionsVisible(bool);
268
269     bool elementIsHidden() const override { return m_elementIsHidden; }
270
271 #if ENABLE(MEDIA_STATISTICS)
272 // Statistics
273     unsigned webkitAudioDecodedByteCount() const;
274     unsigned webkitVideoDecodedByteCount() const;
275 #endif
276
277 #if ENABLE(MEDIA_SOURCE)
278 //  Media Source.
279     void detachMediaSource();
280     void incrementDroppedFrameCount() { ++m_droppedVideoFrames; }
281     size_t maximumSourceBufferSize(const SourceBuffer&) const;
282 #endif
283
284 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
285     WebKitMediaKeys* webkitKeys() const { return m_webKitMediaKeys.get(); }
286     void webkitSetMediaKeys(WebKitMediaKeys*);
287
288     void keyAdded();
289 #endif
290
291 #if ENABLE(ENCRYPTED_MEDIA)
292     MediaKeys* mediaKeys() const;
293
294     void setMediaKeys(MediaKeys*, Ref<DeferredPromise>&&);
295 #endif
296
297 // controls
298     WEBCORE_EXPORT bool controls() const;
299     WEBCORE_EXPORT void setControls(bool);
300     WEBCORE_EXPORT double volume() const override;
301     ExceptionOr<void> setVolume(double) override;
302     WEBCORE_EXPORT bool muted() const override;
303     WEBCORE_EXPORT void setMuted(bool) override;
304
305     WEBCORE_EXPORT void togglePlayState();
306     WEBCORE_EXPORT void beginScrubbing() override;
307     WEBCORE_EXPORT void endScrubbing() override;
308
309     void beginScanning(ScanDirection) override;
310     void endScanning() override;
311     double nextScanRate();
312
313     WEBCORE_EXPORT bool canPlay() const override;
314
315     double percentLoaded() const;
316
317     bool shouldForceControlsDisplay() const;
318
319 #if ENABLE(VIDEO_TRACK)
320     ExceptionOr<TextTrack&> addTextTrack(const String& kind, const String& label, const String& language);
321
322     AudioTrackList& audioTracks();
323     TextTrackList& textTracks();
324     VideoTrackList& videoTracks();
325
326     CueList currentlyActiveCues() const { return m_currentlyActiveCues; }
327
328     void addAudioTrack(Ref<AudioTrack>&&);
329     void addTextTrack(Ref<TextTrack>&&);
330     void addVideoTrack(Ref<VideoTrack>&&);
331     void removeAudioTrack(AudioTrack&);
332     void removeTextTrack(TextTrack&, bool scheduleEvent = true);
333     void removeVideoTrack(VideoTrack&);
334     void forgetResourceSpecificTracks();
335     void closeCaptionTracksChanged();
336     void notifyMediaPlayerOfTextTrackChanges();
337
338     virtual void didAddTextTrack(HTMLTrackElement&);
339     virtual void didRemoveTextTrack(HTMLTrackElement&);
340
341     void mediaPlayerDidAddAudioTrack(AudioTrackPrivate&) final;
342     void mediaPlayerDidAddTextTrack(InbandTextTrackPrivate&) final;
343     void mediaPlayerDidAddVideoTrack(VideoTrackPrivate&) final;
344     void mediaPlayerDidRemoveAudioTrack(AudioTrackPrivate&) final;
345     void mediaPlayerDidRemoveTextTrack(InbandTextTrackPrivate&) final;
346     void mediaPlayerDidRemoveVideoTrack(VideoTrackPrivate&) final;
347
348 #if ENABLE(AVF_CAPTIONS)
349     Vector<RefPtr<PlatformTextTrack>> outOfBandTrackSources() final;
350 #endif
351
352     struct TrackGroup;
353     void configureTextTrackGroupForLanguage(const TrackGroup&) const;
354     void configureTextTracks();
355     void configureTextTrackGroup(const TrackGroup&);
356
357     void setSelectedTextTrack(TextTrack*);
358
359     bool textTracksAreReady() const;
360     using HTMLMediaElementEnums::TextTrackVisibilityCheckType;
361     void configureTextTrackDisplay(TextTrackVisibilityCheckType checkType = CheckTextTrackVisibility);
362     void updateTextTrackDisplay();
363
364     // AudioTrackClient
365     void audioTrackEnabledChanged(AudioTrack&) final;
366
367     void textTrackReadyStateChanged(TextTrack*);
368
369     // TextTrackClient
370     void textTrackKindChanged(TextTrack&) override;
371     void textTrackModeChanged(TextTrack&) override;
372     void textTrackAddCues(TextTrack&, const TextTrackCueList&) override;
373     void textTrackRemoveCues(TextTrack&, const TextTrackCueList&) override;
374     void textTrackAddCue(TextTrack&, TextTrackCue&) override;
375     void textTrackRemoveCue(TextTrack&, TextTrackCue&) override;
376
377     // VideoTrackClient
378     void videoTrackSelectedChanged(VideoTrack&) final;
379
380     bool requiresTextTrackRepresentation() const;
381     void setTextTrackRepresentation(TextTrackRepresentation*);
382     void syncTextTrackBounds();
383 #endif
384
385 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
386     void webkitShowPlaybackTargetPicker();
387     bool addEventListener(const AtomicString& eventType, Ref<EventListener>&&, const AddEventListenerOptions&) override;
388     bool removeEventListener(const AtomicString& eventType, EventListener&, const ListenerOptions&) override;
389
390     void wirelessRoutesAvailableDidChange() override;
391     bool canPlayToWirelessPlaybackTarget() const override;
392     bool isPlayingToWirelessPlaybackTarget() const override;
393     void setWirelessPlaybackTarget(Ref<MediaPlaybackTarget>&&) override;
394     void setShouldPlayToPlaybackTarget(bool) override;
395 #endif
396     bool webkitCurrentPlaybackTargetIsWireless() const;
397
398     // EventTarget function.
399     // Both Node (via HTMLElement) and ActiveDOMObject define this method, which
400     // causes an ambiguity error at compile time. This class's constructor
401     // ensures that both implementations return document, so return the result
402     // of one of them here.
403     using HTMLElement::scriptExecutionContext;
404
405     bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
406     
407     WEBCORE_EXPORT bool isFullscreen() const override;
408     bool isStandardFullscreen() const;
409     void toggleStandardFullscreenState();
410
411     using MediaPlayerEnums::VideoFullscreenMode;
412     VideoFullscreenMode fullscreenMode() const { return m_videoFullscreenMode; }
413     virtual void fullscreenModeChanged(VideoFullscreenMode);
414
415     void enterFullscreen(VideoFullscreenMode);
416     void enterFullscreen() override;
417     WEBCORE_EXPORT void exitFullscreen();
418
419     bool hasClosedCaptions() const override;
420     bool closedCaptionsVisible() const override;
421     void setClosedCaptionsVisible(bool) override;
422
423     MediaControls* mediaControls() const;
424
425     void sourceWasRemoved(HTMLSourceElement&);
426     void sourceWasAdded(HTMLSourceElement&);
427
428     void privateBrowsingStateDidChange() override;
429
430     // Media cache management.
431     WEBCORE_EXPORT static void setMediaCacheDirectory(const String&);
432     WEBCORE_EXPORT static const String& mediaCacheDirectory();
433     WEBCORE_EXPORT static HashSet<RefPtr<SecurityOrigin>> originsInMediaCache(const String&);
434     WEBCORE_EXPORT static void clearMediaCache(const String&, std::chrono::system_clock::time_point modifiedSince = { });
435     WEBCORE_EXPORT static void clearMediaCacheForOrigins(const String&, const HashSet<RefPtr<SecurityOrigin>>&);
436     static void resetMediaEngines();
437
438     bool isPlaying() const { return m_playing; }
439
440     bool hasPendingActivity() const override;
441
442 #if ENABLE(WEB_AUDIO)
443     MediaElementAudioSourceNode* audioSourceNode() { return m_audioSourceNode; }
444     void setAudioSourceNode(MediaElementAudioSourceNode*);
445
446     AudioSourceProvider* audioSourceProvider();
447 #endif
448
449     using HTMLMediaElementEnums::InvalidURLAction;
450     bool isSafeToLoadURL(const URL&, InvalidURLAction);
451
452     const String& mediaGroup() const;
453     void setMediaGroup(const String&);
454
455     MediaController* controller() const;
456     void setController(RefPtr<MediaController>&&);
457
458     MediaController* controllerForBindings() const { return controller(); }
459     void setControllerForBindings(MediaController*);
460
461     void enteredOrExitedFullscreen() { configureMediaControls(); }
462
463     unsigned long long fileSize() const;
464
465     void mediaLoadingFailed(MediaPlayerEnums::NetworkState);
466     void mediaLoadingFailedFatally(MediaPlayerEnums::NetworkState);
467
468 #if ENABLE(MEDIA_SESSION)
469     WEBCORE_EXPORT double playerVolume() const;
470
471     const String& kind() const { return m_kind; }
472     void setKind(const String& kind) { m_kind = kind; }
473
474     MediaSession* session() const;
475     void setSession(MediaSession*);
476
477     void setShouldDuck(bool);
478
479     static HTMLMediaElement* elementWithID(uint64_t);
480     uint64_t elementID() const { return m_elementID; }
481 #endif
482
483 #if ENABLE(MEDIA_SOURCE)
484     RefPtr<VideoPlaybackQuality> getVideoPlaybackQuality();
485 #endif
486
487     MediaPlayerEnums::Preload preloadValue() const { return m_preload; }
488     MediaElementSession& mediaSession() const { return *m_mediaSession; }
489
490 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
491     void pageScaleFactorChanged();
492     void userInterfaceLayoutDirectionChanged();
493     WEBCORE_EXPORT String getCurrentMediaControlsStatus();
494
495     MediaControlsHost* mediaControlsHost() { return m_mediaControlsHost.get(); }
496 #endif
497
498     bool isDisablingSleep() const { return m_sleepDisabler.get(); }
499
500     double maxBufferedTime() const;
501
502     MediaProducer::MediaStateFlags mediaState() const override;
503
504     void layoutSizeChanged();
505     void visibilityDidChange();
506
507     void allowsMediaDocumentInlinePlaybackChanged();
508     void updateShouldPlay();
509
510     RenderMedia* renderer() const;
511
512     void resetPlaybackSessionState();
513     bool isVisibleInViewport() const;
514     bool hasEverNotifiedAboutPlaying() const;
515     void setShouldDelayLoadEvent(bool);
516
517     bool hasEverHadAudio() const { return m_hasEverHadAudio; }
518     bool hasEverHadVideo() const { return m_hasEverHadVideo; }
519
520     double playbackStartedTime() const { return m_playbackStartedTime; }
521
522     bool isTemporarilyAllowingInlinePlaybackAfterFullscreen() const {return m_temporarilyAllowingInlinePlaybackAfterFullscreen; }
523
524     void isVisibleInViewportChanged();
525     void updateRateChangeRestrictions();
526
527     WEBCORE_EXPORT const MediaResourceLoader* lastMediaResourceLoaderForTesting() const;
528
529 #if ENABLE(MEDIA_STREAM)
530     void mediaStreamCaptureStarted() { resumeAutoplaying(); }
531     bool hasMediaStreamSrcObject() const { return !!m_mediaStreamSrcObject; }
532 #endif
533
534     bool supportsSeeking() const override;
535
536 protected:
537     HTMLMediaElement(const QualifiedName&, Document&, bool createdByParser);
538     virtual ~HTMLMediaElement();
539
540     void parseAttribute(const QualifiedName&, const AtomicString&) override;
541     void finishParsingChildren() override;
542     bool isURLAttribute(const Attribute&) const override;
543     void willAttachRenderers() override;
544     void didAttachRenderers() override;
545     void willDetachRenderers() override;
546     void didDetachRenderers() override;
547
548     void didMoveToNewDocument(Document& oldDocument, Document& newDocument) override;
549
550     enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video };
551     DisplayMode displayMode() const { return m_displayMode; }
552     virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; }
553     
554     bool isMediaElement() const final { return true; }
555
556 #if ENABLE(VIDEO_TRACK)
557     bool ignoreTrackDisplayUpdateRequests() const { return m_ignoreTrackDisplayUpdate > 0 || !m_textTracks || !m_cueTree.size(); }
558     void beginIgnoringTrackDisplayUpdateRequests();
559     void endIgnoringTrackDisplayUpdateRequests();
560 #endif
561
562     RenderPtr<RenderElement> createElementRenderer(RenderStyle&&, const RenderTreePosition&) override;
563
564 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
565     bool mediaControlsDependOnPageScaleFactor() const { return m_mediaControlsDependOnPageScaleFactor; }
566     void setMediaControlsDependOnPageScaleFactor(bool);
567     void updateMediaControlsAfterPresentationModeChange();
568 #endif
569
570     void scheduleEvent(const AtomicString& eventName);
571
572 private:
573     void createMediaPlayer();
574
575     bool alwaysCreateUserAgentShadowRoot() const override { return true; }
576
577     bool supportsFocus() const override;
578     bool isMouseFocusable() const override;
579     bool rendererIsNeeded(const RenderStyle&) override;
580     bool childShouldCreateRenderer(const Node&) const override;
581     InsertionNotificationRequest insertedInto(ContainerNode&) override;
582     void finishedInsertingSubtree() override;
583     void removedFrom(ContainerNode&) override;
584     void didRecalcStyle(Style::Change) override;
585
586     void willBecomeFullscreenElement() override;
587     void didBecomeFullscreenElement() override;
588     void willStopBeingFullscreenElement() override;
589
590     // ActiveDOMObject API.
591     const char* activeDOMObjectName() const override;
592     bool canSuspendForDocumentSuspension() const override;
593     void suspend(ReasonForSuspension) override;
594     void resume() override;
595     void stop() override;
596     void stopWithoutDestroyingMediaPlayer();
597     void contextDestroyed() override;
598     
599     void mediaVolumeDidChange() override;
600
601     void visibilityStateChanged() override;
602
603     virtual void updateDisplayState() { }
604     
605     void setReadyState(MediaPlayerEnums::ReadyState);
606     void setNetworkState(MediaPlayerEnums::NetworkState);
607
608     double effectivePlaybackRate() const;
609     double requestedPlaybackRate() const;
610
611     void mediaPlayerNetworkStateChanged(MediaPlayer*) override;
612     void mediaPlayerReadyStateChanged(MediaPlayer*) override;
613     void mediaPlayerTimeChanged(MediaPlayer*) override;
614     void mediaPlayerVolumeChanged(MediaPlayer*) override;
615     void mediaPlayerMuteChanged(MediaPlayer*) override;
616     void mediaPlayerDurationChanged(MediaPlayer*) override;
617     void mediaPlayerRateChanged(MediaPlayer*) override;
618     void mediaPlayerPlaybackStateChanged(MediaPlayer*) override;
619     void mediaPlayerSawUnsupportedTracks(MediaPlayer*) override;
620     void mediaPlayerResourceNotSupported(MediaPlayer*) override;
621     void mediaPlayerRepaint(MediaPlayer*) override;
622     void mediaPlayerSizeChanged(MediaPlayer*) override;
623     bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*) override;
624     void mediaPlayerRenderingModeChanged(MediaPlayer*) override;
625     bool mediaPlayerAcceleratedCompositingEnabled() override;
626     void mediaPlayerEngineUpdated(MediaPlayer*) override;
627     void mediaEngineWasUpdated();
628
629     void mediaPlayerFirstVideoFrameAvailable(MediaPlayer*) override;
630     void mediaPlayerCharacteristicChanged(MediaPlayer*) override;
631
632 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
633     RefPtr<ArrayBuffer> mediaPlayerCachedKeyForKeyId(const String& keyId) const override;
634     bool mediaPlayerKeyNeeded(MediaPlayer*, Uint8Array*) override;
635     String mediaPlayerMediaKeysStorageDirectory() const override;
636 #endif
637
638 #if ENABLE(ENCRYPTED_MEDIA)
639     void attemptToResumePlaybackIfNecessary();
640
641     // CDMClient
642     void cdmClientAttemptToResumePlaybackIfNecessary() override;
643 #endif
644     
645 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
646     void mediaPlayerCurrentPlaybackTargetIsWirelessChanged(MediaPlayer*) override;
647     void enqueuePlaybackTargetAvailabilityChangedEvent();
648
649     using EventTarget::dispatchEvent;
650     bool dispatchEvent(Event&) override;
651 #endif
652
653 #if ENABLE(MEDIA_SESSION)
654     void setSessionInternal(MediaSession&);
655 #endif
656
657     String mediaPlayerReferrer() const override;
658     String mediaPlayerUserAgent() const override;
659
660     bool mediaPlayerNeedsSiteSpecificHacks() const override;
661     String mediaPlayerDocumentHost() const override;
662
663     void mediaPlayerEnterFullscreen() override;
664     void mediaPlayerExitFullscreen() override;
665     bool mediaPlayerIsFullscreen() const override;
666     bool mediaPlayerIsFullscreenPermitted() const override;
667     bool mediaPlayerIsVideo() const override;
668     LayoutRect mediaPlayerContentBoxRect() const override;
669     float mediaPlayerContentsScale() const override;
670     void mediaPlayerSetSize(const IntSize&) override;
671     void mediaPlayerPause() override;
672     void mediaPlayerPlay() override;
673     bool mediaPlayerPlatformVolumeConfigurationRequired() const override;
674     bool mediaPlayerIsPaused() const override;
675     bool mediaPlayerIsLooping() const override;
676     CachedResourceLoader* mediaPlayerCachedResourceLoader() override;
677     RefPtr<PlatformMediaResourceLoader> mediaPlayerCreateResourceLoader() override;
678     bool mediaPlayerShouldUsePersistentCache() const override;
679     const String& mediaPlayerMediaCacheDirectory() const override;
680
681 #if PLATFORM(WIN) && USE(AVFOUNDATION)
682     GraphicsDeviceAdapter* mediaPlayerGraphicsDeviceAdapter(const MediaPlayer*) const override;
683 #endif
684
685     void mediaPlayerActiveSourceBuffersChanged(const MediaPlayer*) override;
686
687     bool mediaPlayerShouldWaitForResponseToAuthenticationChallenge(const AuthenticationChallenge&) override;
688     void mediaPlayerHandlePlaybackCommand(PlatformMediaSession::RemoteControlCommandType command) override { didReceiveRemoteControlCommand(command, nullptr); }
689     String sourceApplicationIdentifier() const override;
690     String mediaPlayerSourceApplicationIdentifier() const override { return sourceApplicationIdentifier(); }
691     Vector<String> mediaPlayerPreferredAudioCharacteristics() const override;
692
693 #if PLATFORM(IOS)
694     String mediaPlayerNetworkInterfaceName() const override;
695     bool mediaPlayerGetRawCookies(const URL&, Vector<Cookie>&) const override;
696 #endif
697
698     bool mediaPlayerIsInMediaDocument() const final;
699     void mediaPlayerEngineFailedToLoad() const final;
700
701     double mediaPlayerRequestedPlaybackRate() const final;
702     VideoFullscreenMode mediaPlayerFullscreenMode() const final { return fullscreenMode(); }
703     bool mediaPlayerShouldDisableSleep() const final { return shouldDisableSleep() == SleepType::Display; }
704     bool mediaPlayerShouldCheckHardwareSupport() const final;
705     const Vector<ContentType>& mediaContentTypesRequiringHardwareSupport() const final;
706
707 #if USE(GSTREAMER)
708     void requestInstallMissingPlugins(const String& details, const String& description, MediaPlayerRequestInstallMissingPluginsCallback&) final;
709 #endif
710
711     void pendingActionTimerFired();
712     void progressEventTimerFired();
713     void playbackProgressTimerFired();
714     void scanTimerFired();
715     void seekTask();
716     void startPlaybackProgressTimer();
717     void startProgressEventTimer();
718     void stopPeriodicTimers();
719
720     void seek(const MediaTime&);
721     void seekInternal(const MediaTime&);
722     void seekWithTolerance(const MediaTime&, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance, bool fromDOM);
723     void finishSeek();
724     void clearSeeking();
725     void addPlayedRange(const MediaTime& start, const MediaTime& end);
726     
727     void scheduleTimeupdateEvent(bool periodicEvent);
728     virtual void scheduleResizeEvent() { }
729     virtual void scheduleResizeEventIfSizeChanged() { }
730
731     void selectMediaResource();
732     void loadResource(const URL&, ContentType&, const String& keySystem);
733     void scheduleNextSourceChild();
734     void loadNextSourceChild();
735     void userCancelledLoad();
736     void clearMediaPlayer(DelayedActionType flags);
737     bool havePotentialSourceChild();
738     void noneSupported();
739     void cancelPendingEventsAndCallbacks();
740     void waitForSourceChange();
741     void prepareToPlay();
742
743     URL selectNextSourceChild(ContentType*, String* keySystem, InvalidURLAction);
744
745 #if ENABLE(VIDEO_TRACK)
746     void updateActiveTextTrackCues(const MediaTime&);
747     HTMLTrackElement* showingTrackWithSameKind(HTMLTrackElement*) const;
748
749     enum ReconfigureMode {
750         Immediately,
751         AfterDelay,
752     };
753     void markCaptionAndSubtitleTracksAsUnconfigured(ReconfigureMode);
754     void captionPreferencesChanged() override;
755 #endif
756
757     // These "internal" functions do not check user gesture restrictions.
758     bool playInternal();
759     void pauseInternal();
760
761     void prepareForLoad();
762     void allowVideoRendering();
763
764     bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; }
765     void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; }
766     void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; }
767
768     enum class UpdateState { Asynchronously, Synchronously };
769
770     void updatePlayState(UpdateState updateState = UpdateState::Synchronously);
771     void updateVolume();
772     void setPlaying(bool);
773     bool potentiallyPlaying() const;
774     bool endedPlayback() const;
775     bool stoppedDueToErrors() const;
776     bool pausedForUserInteraction() const;
777     bool couldPlayIfEnoughData() const;
778     void dispatchPlayPauseEventsIfNeedsQuirks();
779     SuccessOr<MediaPlaybackDenialReason> canTransitionFromAutoplayToPlay() const;
780
781     enum class PlaybackWithoutUserGesture { None, Started, Prevented };
782     void setPlaybackWithoutUserGesture(PlaybackWithoutUserGesture);
783     void userDidInterfereWithAutoplay();
784     void handleAutoplayEvent(AutoplayEvent);
785
786     MediaTime minTimeSeekable() const;
787     MediaTime maxTimeSeekable() const;
788
789     // Pauses playback without changing any states or generating events
790     void setPausedInternal(bool);
791
792     void setPlaybackRateInternal(double);
793
794     void mediaCanStart(Document&) final;
795
796     void invalidateCachedTime() const;
797     void refreshCachedTime() const;
798
799     bool hasMediaControls() const;
800     bool createMediaControls();
801     void configureMediaControls();
802
803     void prepareMediaFragmentURI();
804     void applyMediaFragmentURI();
805
806     void changeNetworkStateFromLoadingToIdle();
807
808     void removeBehaviorsRestrictionsAfterFirstUserGesture(MediaElementSession::BehaviorRestrictions mask = MediaElementSession::AllRestrictions);
809
810     void updateMediaController();
811     bool isBlocked() const;
812     bool isBlockedOnMediaController() const;
813     bool hasCurrentSrc() const override { return !m_currentSrc.isEmpty(); }
814     bool isLiveStream() const override { return movieLoadType() == MediaPlayerEnums::LiveStream; }
815
816     void updateSleepDisabling();
817     enum class SleepType {
818         None,
819         Display,
820         System,
821     };
822     SleepType shouldDisableSleep() const;
823
824 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
825     void didAddUserAgentShadowRoot(ShadowRoot*) override;
826     DOMWrapperWorld& ensureIsolatedWorld();
827     bool ensureMediaControlsInjectedScript();
828 #endif
829
830     PlatformMediaSession::MediaType mediaType() const override;
831     PlatformMediaSession::MediaType presentationType() const override;
832     PlatformMediaSession::DisplayType displayType() const override;
833     PlatformMediaSession::CharacteristicsFlags characteristics() const final;
834
835     void suspendPlayback() override;
836     void resumeAutoplaying() override;
837     void mayResumePlayback(bool shouldResume) override;
838     String mediaSessionTitle() const override;
839     double mediaSessionDuration() const override { return duration(); }
840     double mediaSessionCurrentTime() const override { return currentTime(); }
841     bool canReceiveRemoteControlCommands() const override { return true; }
842     void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) override;
843     bool shouldOverrideBackgroundPlaybackRestriction(PlatformMediaSession::InterruptionType) const override;
844     bool shouldOverrideBackgroundLoadingRestriction() const override;
845     bool canProduceAudio() const final;
846     bool processingUserGestureForMedia() const final;
847     bool isSuspended() const final;
848
849     void pageMutedStateDidChange() override;
850
851 #if USE(AUDIO_SESSION) && PLATFORM(MAC)
852     void hardwareMutedStateDidChange(AudioSession*) final;
853 #endif
854
855     bool effectiveMuted() const;
856
857     void registerWithDocument(Document&);
858     void unregisterWithDocument(Document&);
859
860     void updateCaptionContainer();
861     void ensureMediaControlsShadowRoot();
862
863 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
864     void prepareForDocumentSuspension() final;
865     void resumeFromDocumentSuspension() final;
866
867     void updateMediaState(UpdateState updateState = UpdateState::Synchronously);
868     bool hasPlaybackTargetAvailabilityListeners() const { return m_hasPlaybackTargetAvailabilityListeners; }
869 #endif
870
871     bool isVideoTooSmallForInlinePlayback();
872     void updateShouldAutoplay();
873
874     void pauseAfterDetachedTask();
875     void updatePlaybackControlsManager();
876     void scheduleUpdatePlaybackControlsManager();
877     void playbackControlsManagerBehaviorRestrictionsTimerFired();
878
879     void updateRenderer();
880
881     void updatePageScaleFactorJSProperty();
882     void updateUsesLTRUserInterfaceLayoutDirectionJSProperty();
883     void setControllerJSProperty(const char*, JSC::JSValue);
884
885     void addBehaviorRestrictionsOnEndIfNecessary();
886     void handleSeekToPlaybackPosition(double);
887     void seekToPlaybackPositionEndedTimerFired();
888
889     WeakPtrFactory<HTMLMediaElement> m_weakFactory;
890     Timer m_pendingActionTimer;
891     Timer m_progressEventTimer;
892     Timer m_playbackProgressTimer;
893     Timer m_scanTimer;
894     Timer m_playbackControlsManagerBehaviorRestrictionsTimer;
895     Timer m_seekToPlaybackPositionEndedTimer;
896     GenericTaskQueue<Timer> m_seekTaskQueue;
897     GenericTaskQueue<Timer> m_shadowDOMTaskQueue;
898     GenericTaskQueue<Timer> m_promiseTaskQueue;
899     GenericTaskQueue<Timer> m_pauseAfterDetachedTaskQueue;
900     GenericTaskQueue<Timer> m_updatePlaybackControlsManagerQueue;
901     GenericTaskQueue<Timer> m_playbackControlsManagerBehaviorRestrictionsQueue;
902     GenericTaskQueue<Timer> m_resourceSelectionTaskQueue;
903     RefPtr<TimeRanges> m_playedTimeRanges;
904     GenericEventQueue m_asyncEventQueue;
905
906     Vector<DOMPromiseDeferred<void>> m_pendingPlayPromises;
907
908     double m_requestedPlaybackRate { 1 };
909     double m_reportedPlaybackRate { 1 };
910     double m_defaultPlaybackRate { 1 };
911     bool m_webkitPreservesPitch { true };
912     NetworkState m_networkState { NETWORK_EMPTY };
913     ReadyState m_readyState { HAVE_NOTHING };
914     ReadyState m_readyStateMaximum { HAVE_NOTHING };
915     URL m_currentSrc;
916
917     RefPtr<MediaError> m_error;
918
919     struct PendingSeek {
920         PendingSeek(const MediaTime& now, const MediaTime& targetTime, const MediaTime& negativeTolerance, const MediaTime& positiveTolerance)
921             : now(now)
922             , targetTime(targetTime)
923             , negativeTolerance(negativeTolerance)
924             , positiveTolerance(positiveTolerance)
925         {
926         }
927         MediaTime now;
928         MediaTime targetTime;
929         MediaTime negativeTolerance;
930         MediaTime positiveTolerance;
931     };
932     std::unique_ptr<PendingSeek> m_pendingSeek;
933     SeekType m_pendingSeekType { NoSeek };
934
935     double m_volume { 1 };
936     bool m_volumeInitialized { false };
937     MediaTime m_lastSeekTime;
938     
939     double m_previousProgressTime { std::numeric_limits<double>::max() };
940     double m_playbackStartedTime { 0 };
941
942     // The last time a timeupdate event was sent (based on monotonic clock).
943     MonotonicTime m_clockTimeAtLastUpdateEvent;
944
945     // The last time a timeupdate event was sent in movie time.
946     MediaTime m_lastTimeUpdateEventMovieTime;
947     
948     // Loading state.
949     enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
950     LoadState m_loadState { WaitingForSource };
951     RefPtr<HTMLSourceElement> m_currentSourceNode;
952     RefPtr<HTMLSourceElement> m_nextChildNodeToConsider;
953
954     VideoFullscreenMode m_videoFullscreenMode { VideoFullscreenModeNone };
955     bool m_preparedForInline;
956     WTF::Function<void()> m_preparedForInlineCompletionHandler;
957
958     bool m_temporarilyAllowingInlinePlaybackAfterFullscreen { false };
959
960 #if PLATFORM(IOS) || (PLATFORM(MAC) && ENABLE(VIDEO_PRESENTATION_MODE))
961     RetainPtr<PlatformLayer> m_videoFullscreenLayer;
962     FloatRect m_videoFullscreenFrame;
963     MediaPlayerEnums::VideoGravity m_videoFullscreenGravity { MediaPlayer::VideoGravityResizeAspect };
964 #endif
965
966     RefPtr<MediaPlayer> m_player;
967
968     MediaPlayerEnums::Preload m_preload { MediaPlayer::Auto };
969
970     DisplayMode m_displayMode { Unknown };
971
972     // Counter incremented while processing a callback from the media player, so we can avoid
973     // calling the media engine recursively.
974     int m_processingMediaPlayerCallback { 0 };
975
976 #if ENABLE(MEDIA_SESSION)
977     String m_kind;
978     RefPtr<MediaSession> m_session;
979     bool m_shouldDuck { false };
980     uint64_t m_elementID;
981 #endif
982
983 #if ENABLE(MEDIA_SOURCE)
984     RefPtr<MediaSource> m_mediaSource;
985     unsigned m_droppedVideoFrames { 0 };
986 #endif
987
988     mutable MediaTime m_cachedTime;
989     mutable double m_clockTimeAtLastCachedTimeUpdate { 0 };
990     mutable double m_minimumClockTimeToUpdateCachedTime { 0 };
991
992     MediaTime m_fragmentStartTime;
993     MediaTime m_fragmentEndTime;
994
995     using PendingActionFlags = unsigned;
996     PendingActionFlags m_pendingActionFlags { 0 };
997
998     enum ActionAfterScanType { Nothing, Play, Pause };
999     ActionAfterScanType m_actionAfterScan { Nothing };
1000
1001     enum ScanType { Seek, Scan };
1002     ScanType m_scanType { Scan };
1003     ScanDirection m_scanDirection { Forward };
1004
1005     bool m_firstTimePlaying : 1;
1006     bool m_playing : 1;
1007     bool m_isWaitingUntilMediaCanStart : 1;
1008     bool m_shouldDelayLoadEvent : 1;
1009     bool m_haveFiredLoadedData : 1;
1010     bool m_inActiveDocument : 1;
1011     bool m_autoplaying : 1;
1012     bool m_muted : 1;
1013     bool m_explicitlyMuted : 1;
1014     bool m_initiallyMuted : 1;
1015     bool m_paused : 1;
1016     bool m_seeking : 1;
1017     bool m_seekRequested : 1;
1018
1019     // data has not been loaded since sending a "stalled" event
1020     bool m_sentStalledEvent : 1;
1021
1022     // time has not changed since sending an "ended" event
1023     bool m_sentEndEvent : 1;
1024
1025     bool m_pausedInternal : 1;
1026
1027     bool m_closedCaptionsVisible : 1;
1028     bool m_webkitLegacyClosedCaptionOverride : 1;
1029     bool m_completelyLoaded : 1;
1030     bool m_havePreparedToPlay : 1;
1031     bool m_parsingInProgress : 1;
1032     bool m_elementIsHidden : 1;
1033     bool m_creatingControls : 1;
1034     bool m_receivedLayoutSizeChanged : 1;
1035     bool m_hasEverNotifiedAboutPlaying : 1;
1036
1037     bool m_hasEverHadAudio : 1;
1038     bool m_hasEverHadVideo : 1;
1039
1040 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
1041     bool m_mediaControlsDependOnPageScaleFactor : 1;
1042     bool m_haveSetUpCaptionContainer : 1;
1043 #endif
1044
1045     bool m_isScrubbingRemotely : 1;
1046
1047 #if ENABLE(VIDEO_TRACK)
1048     bool m_tracksAreReady : 1;
1049     bool m_haveVisibleTextTrack : 1;
1050     bool m_processingPreferenceChange : 1;
1051
1052     PlaybackWithoutUserGesture m_playbackWithoutUserGesture { PlaybackWithoutUserGesture::None };
1053     std::optional<MediaTime> m_playbackWithoutUserGestureStartedTime;
1054
1055     String m_subtitleTrackLanguage;
1056     MediaTime m_lastTextTrackUpdateTime { -1, 1 };
1057
1058     CaptionUserPreferences::CaptionDisplayMode m_captionDisplayMode { CaptionUserPreferences::Automatic };
1059
1060     RefPtr<AudioTrackList> m_audioTracks;
1061     RefPtr<TextTrackList> m_textTracks;
1062     RefPtr<VideoTrackList> m_videoTracks;
1063     Vector<RefPtr<TextTrack>> m_textTracksWhenResourceSelectionBegan;
1064
1065     CueIntervalTree m_cueTree;
1066
1067     CueList m_currentlyActiveCues;
1068     int m_ignoreTrackDisplayUpdate { 0 };
1069
1070     bool m_requireCaptionPreferencesChangedCallbacks { false };
1071 #endif
1072
1073 #if ENABLE(WEB_AUDIO)
1074     // This is a weak reference, since m_audioSourceNode holds a reference to us.
1075     // The value is set just after the MediaElementAudioSourceNode is created.
1076     // The value is cleared in MediaElementAudioSourceNode::~MediaElementAudioSourceNode().
1077     MediaElementAudioSourceNode* m_audioSourceNode { nullptr };
1078 #endif
1079
1080     String m_mediaGroup;
1081     friend class MediaController;
1082     RefPtr<MediaController> m_mediaController;
1083
1084     std::unique_ptr<PAL::SleepDisabler> m_sleepDisabler;
1085
1086     WeakPtr<const MediaResourceLoader> m_lastMediaResourceLoaderForTesting;
1087
1088     friend class TrackDisplayUpdateScope;
1089
1090     RefPtr<Blob> m_blob;
1091     MediaProvider m_mediaProvider;
1092
1093 #if ENABLE(LEGACY_ENCRYPTED_MEDIA)
1094     RefPtr<WebKitMediaKeys> m_webKitMediaKeys;
1095 #endif
1096 #if ENABLE(ENCRYPTED_MEDIA)
1097     RefPtr<MediaKeys> m_mediaKeys;
1098     bool m_attachingMediaKeys { false };
1099     GenericTaskQueue<Timer> m_encryptedMediaQueue;
1100 #endif
1101
1102     std::unique_ptr<MediaElementSession> m_mediaSession;
1103     size_t m_reportedExtraMemoryCost { 0 };
1104
1105 #if ENABLE(MEDIA_CONTROLS_SCRIPT)
1106     friend class MediaControlsHost;
1107     RefPtr<MediaControlsHost> m_mediaControlsHost;
1108     RefPtr<DOMWrapperWorld> m_isolatedWorld;
1109 #endif
1110
1111 #if ENABLE(MEDIA_STREAM)
1112     RefPtr<MediaStream> m_mediaStreamSrcObject;
1113     bool m_settingMediaStreamSrcObject { false };
1114 #endif
1115
1116 #if ENABLE(WIRELESS_PLAYBACK_TARGET)
1117     MediaProducer::MediaStateFlags m_mediaState { MediaProducer::IsNotPlaying };
1118     bool m_hasPlaybackTargetAvailabilityListeners { false };
1119     bool m_failedToPlayToWirelessTarget { false };
1120     bool m_isPlayingToWirelessTarget { false };
1121 #endif
1122 };
1123
1124 } // namespace WebCore
1125
1126 #if ENABLE(VIDEO_TRACK) && !defined(NDEBUG)
1127 namespace WTF {
1128
1129 // Template specialization required by PodIntervalTree in debug mode.
1130 template <> struct ValueToString<WebCore::TextTrackCue*> {
1131     static String string(WebCore::TextTrackCue* const& cue)
1132     {
1133         String text;
1134         if (cue->isRenderable())
1135             text = WebCore::toVTTCue(cue)->text();
1136         return String::format("%p id=%s interval=%s-->%s cue=%s)", cue, cue->id().utf8().data(), toString(cue->startTime()).utf8().data(), toString(cue->endTime()).utf8().data(), text.utf8().data());
1137     }
1138 };
1139
1140 } // namespace WTF
1141 #endif
1142
1143 #ifndef NDEBUG
1144 namespace WTF {
1145
1146 template<> struct ValueToString<MediaTime> {
1147     static String string(const MediaTime& time)
1148     {
1149         return toString(time);
1150     }
1151 };
1152
1153 } // namespace WTF
1154 #endif
1155
1156 SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::HTMLMediaElement)
1157     static bool isType(const WebCore::Element& element) { return element.isMediaElement(); }
1158     static bool isType(const WebCore::Node& node) { return is<WebCore::Element>(node) && isType(downcast<WebCore::Element>(node)); }
1159 SPECIALIZE_TYPE_TRAITS_END()
1160
1161 #endif