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