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