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