1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 #ifndef mozilla_dom_HTMLMediaElement_h 7 #define mozilla_dom_HTMLMediaElement_h 8 9 #include "nsGenericHTMLElement.h" 10 #include "AudioChannelService.h" 11 #include "MediaEventSource.h" 12 #include "SeekTarget.h" 13 #include "MediaDecoderOwner.h" 14 #include "MediaPlaybackDelayPolicy.h" 15 #include "MediaPromiseDefs.h" 16 #include "nsCycleCollectionParticipant.h" 17 #include "Visibility.h" 18 #include "mozilla/CORSMode.h" 19 #include "DecoderTraits.h" 20 #include "mozilla/Attributes.h" 21 #include "mozilla/StateWatching.h" 22 #include "mozilla/WeakPtr.h" 23 #include "mozilla/dom/HTMLMediaElementBinding.h" 24 #include "mozilla/dom/MediaControlKeysEvent.h" 25 #include "mozilla/dom/MediaDebugInfoBinding.h" 26 #include "mozilla/dom/MediaKeys.h" 27 #include "mozilla/dom/TextTrackManager.h" 28 #include "nsGkAtoms.h" 29 #include "PrincipalChangeObserver.h" 30 #include "nsStubMutationObserver.h" 31 #include "MediaSegment.h" // for PrincipalHandle, GraphTime 32 33 #include <utility> 34 35 // X.h on Linux #defines CurrentTime as 0L, so we have to #undef it here. 36 #ifdef CurrentTime 37 # undef CurrentTime 38 #endif 39 40 // Define to output information on decoding and painting framerate 41 /* #define DEBUG_FRAME_RATE 1 */ 42 43 typedef uint16_t nsMediaNetworkState; 44 typedef uint16_t nsMediaReadyState; 45 typedef uint32_t SuspendTypes; 46 typedef uint32_t AudibleChangedReasons; 47 48 namespace mozilla { 49 class AbstractThread; 50 class ChannelMediaDecoder; 51 class DecoderDoctorDiagnostics; 52 class DOMMediaStream; 53 class ErrorResult; 54 class MediaResource; 55 class MediaDecoder; 56 class MediaInputPort; 57 class MediaTrack; 58 class MediaTrackGraph; 59 class MediaStreamWindowCapturer; 60 struct SharedDummyTrack; 61 class VideoFrameContainer; 62 namespace dom { 63 class MediaKeys; 64 class TextTrack; 65 class TimeRanges; 66 class WakeLock; 67 class MediaStreamTrack; 68 class MediaStreamTrackSource; 69 class MediaTrack; 70 class VideoStreamTrack; 71 } // namespace dom 72 } // namespace mozilla 73 74 class AudioDeviceInfo; 75 class nsIChannel; 76 class nsIHttpChannel; 77 class nsILoadGroup; 78 class nsIRunnable; 79 class nsISerialEventTarget; 80 class nsITimer; 81 class nsRange; 82 83 namespace mozilla { 84 namespace dom { 85 86 // Number of milliseconds between timeupdate events as defined by spec 87 #define TIMEUPDATE_MS 250 88 89 class MediaError; 90 class MediaSource; 91 class PlayPromise; 92 class Promise; 93 class TextTrackList; 94 class AudioTrackList; 95 class VideoTrackList; 96 97 enum class StreamCaptureType : uint8_t { CAPTURE_ALL_TRACKS, CAPTURE_AUDIO }; 98 99 enum class StreamCaptureBehavior : uint8_t { 100 CONTINUE_WHEN_ENDED, 101 FINISH_WHEN_ENDED 102 }; 103 104 class HTMLMediaElement : public nsGenericHTMLElement, 105 public MediaDecoderOwner, 106 public PrincipalChangeObserver<MediaStreamTrack>, 107 public SupportsWeakPtr<HTMLMediaElement>, 108 public nsStubMutationObserver { 109 public: 110 typedef mozilla::TimeStamp TimeStamp; 111 typedef mozilla::layers::ImageContainer ImageContainer; 112 typedef mozilla::VideoFrameContainer VideoFrameContainer; 113 typedef mozilla::MediaResource MediaResource; 114 typedef mozilla::MediaDecoderOwner MediaDecoderOwner; 115 typedef mozilla::MetadataTags MetadataTags; 116 117 // Helper struct to keep track of the MediaStreams returned by 118 // mozCaptureStream(). For each OutputMediaStream, dom::MediaTracks get 119 // captured into MediaStreamTracks which get added to 120 // OutputMediaStream::mStream. 121 struct OutputMediaStream { 122 OutputMediaStream(RefPtr<DOMMediaStream> aStream, bool aCapturingAudioOnly, 123 bool aFinishWhenEnded); 124 ~OutputMediaStream(); 125 126 RefPtr<DOMMediaStream> mStream; 127 nsTArray<RefPtr<MediaStreamTrack>> mLiveTracks; 128 const bool mCapturingAudioOnly; 129 const bool mFinishWhenEnded; 130 // If mFinishWhenEnded is true, this is the URI of the first resource 131 // mStream got tracks for, if not a MediaStream. 132 nsCOMPtr<nsIURI> mFinishWhenEndedLoadingSrc; 133 // If mFinishWhenEnded is true, this is the first MediaStream mStream got 134 // tracks for, if not a resource. 135 RefPtr<DOMMediaStream> mFinishWhenEndedAttrStream; 136 }; 137 MOZ_DECLARE_WEAKREFERENCE_TYPENAME(HTMLMediaElement)138 MOZ_DECLARE_WEAKREFERENCE_TYPENAME(HTMLMediaElement) 139 NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED 140 141 CORSMode GetCORSMode() { return mCORSMode; } 142 143 explicit HTMLMediaElement( 144 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo); 145 void Init(); 146 147 void ReportCanPlayTelemetry(); 148 149 /** 150 * This is used when the browser is constructing a video element to play 151 * a channel that we've already started loading. The src attribute and 152 * <source> children are ignored. 153 * @param aChannel the channel to use 154 * @param aListener returns a stream listener that should receive 155 * notifications for the stream 156 */ 157 nsresult LoadWithChannel(nsIChannel* aChannel, nsIStreamListener** aListener); 158 159 // nsISupports 160 NS_DECL_ISUPPORTS_INHERITED 161 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLMediaElement, 162 nsGenericHTMLElement) 163 NS_IMPL_FROMNODE_HELPER(HTMLMediaElement, 164 IsAnyOfHTMLElements(nsGkAtoms::video, 165 nsGkAtoms::audio)) 166 167 NS_DECL_ADDSIZEOFEXCLUDINGTHIS 168 169 // EventTarget 170 void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; 171 172 virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute, 173 const nsAString& aValue, 174 nsIPrincipal* aMaybeScriptedPrincipal, 175 nsAttrValue& aResult) override; 176 177 virtual nsresult BindToTree(BindContext&, nsINode& aParent) override; 178 virtual void UnbindFromTree(bool aNullParent = true) override; 179 virtual void DoneCreatingElement() override; 180 181 virtual bool IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable, 182 int32_t* aTabIndex) override; 183 virtual int32_t TabIndexDefault() override; 184 185 // Called by the video decoder object, on the main thread, 186 // when it has read the metadata containing video dimensions, 187 // etc. 188 virtual void MetadataLoaded(const MediaInfo* aInfo, 189 UniquePtr<const MetadataTags> aTags) final; 190 191 // Called by the decoder object, on the main thread, 192 // when it has read the first frame of the video or audio. 193 void FirstFrameLoaded() final; 194 195 // Called by the video decoder object, on the main thread, 196 // when the resource has a network error during loading. 197 void NetworkError(const MediaResult& aError) final; 198 199 // Called by the video decoder object, on the main thread, when the 200 // resource has a decode error during metadata loading or decoding. 201 void DecodeError(const MediaResult& aError) final; 202 203 // Called by the decoder object, on the main thread, when the 204 // resource has a decode issue during metadata loading or decoding, but can 205 // continue decoding. 206 void DecodeWarning(const MediaResult& aError) final; 207 208 // Return true if error attribute is not null. 209 bool HasError() const final; 210 211 // Called by the video decoder object, on the main thread, when the 212 // resource load has been cancelled. 213 void LoadAborted() final; 214 215 // Called by the video decoder object, on the main thread, 216 // when the video playback has ended. 217 void PlaybackEnded() final; 218 219 // Called by the video decoder object, on the main thread, 220 // when the resource has started seeking. 221 void SeekStarted() final; 222 223 // Called by the video decoder object, on the main thread, 224 // when the resource has completed seeking. 225 void SeekCompleted() final; 226 227 // Called by the video decoder object, on the main thread, 228 // when the resource has aborted seeking. 229 void SeekAborted() final; 230 231 // Called by the media stream, on the main thread, when the download 232 // has been suspended by the cache or because the element itself 233 // asked the decoder to suspend the download. 234 void DownloadSuspended() final; 235 236 // Called by the media stream, on the main thread, when the download 237 // has been resumed by the cache or because the element itself 238 // asked the decoder to resumed the download. 239 void DownloadResumed(); 240 241 // Called to indicate the download is progressing. 242 void DownloadProgressed() final; 243 244 // Called by the media decoder to indicate whether the media cache has 245 // suspended the channel. 246 void NotifySuspendedByCache(bool aSuspendedByCache) final; 247 248 bool IsActive() const; 249 250 bool IsHidden() const; 251 252 // Called by the media decoder and the video frame to get the 253 // ImageContainer containing the video data. 254 VideoFrameContainer* GetVideoFrameContainer() final; 255 layers::ImageContainer* GetImageContainer(); 256 257 /** 258 * Call this to reevaluate whether we should start/stop due to our owner 259 * document being active, inactive, visible or hidden. 260 */ 261 void NotifyOwnerDocumentActivityChanged(); 262 263 // From PrincipalChangeObserver<MediaStreamTrack>. 264 void PrincipalChanged(MediaStreamTrack* aTrack) override; 265 266 void UpdateSrcStreamVideoPrincipal(const PrincipalHandle& aPrincipalHandle); 267 268 // Called after the MediaStream we're playing rendered a frame to aContainer 269 // with a different principalHandle than the previous frame. 270 void PrincipalHandleChangedForVideoFrameContainer( 271 VideoFrameContainer* aContainer, 272 const PrincipalHandle& aNewPrincipalHandle) override; 273 274 // Dispatch events 275 void DispatchAsyncEvent(const nsAString& aName) final; 276 277 // Triggers a recomputation of readyState. UpdateReadyState()278 void UpdateReadyState() override { 279 mWatchManager.ManualNotify(&HTMLMediaElement::UpdateReadyStateInternal); 280 } 281 282 // Dispatch events that were raised while in the bfcache 283 nsresult DispatchPendingMediaEvents(); 284 285 // Return true if we can activate autoplay assuming enough data has arrived. 286 bool CanActivateAutoplay(); 287 288 // Notify that state has changed that might cause an autoplay element to 289 // start playing. 290 // If the element is 'autoplay' and is ready to play back (not paused, 291 // autoplay pref enabled, etc), it should start playing back. 292 void CheckAutoplayDataReady(); 293 294 // Check if the media element had crossorigin set when loading started 295 bool ShouldCheckAllowOrigin(); 296 297 // Returns true if the currently loaded resource is CORS same-origin with 298 // respect to the document. 299 bool IsCORSSameOrigin(); 300 301 // Is the media element potentially playing as defined by the HTML 5 302 // specification. 303 // http://www.whatwg.org/specs/web-apps/current-work/#potentially-playing 304 bool IsPotentiallyPlaying() const; 305 306 // Has playback ended as defined by the HTML 5 specification. 307 // http://www.whatwg.org/specs/web-apps/current-work/#ended 308 bool IsPlaybackEnded() const; 309 310 // principal of the currently playing resource. Anything accessing the 311 // contents of this element must have a principal that subsumes this 312 // principal. Returns null if nothing is playing. 313 already_AddRefed<nsIPrincipal> GetCurrentPrincipal(); 314 315 // Return true if the loading of this resource required cross-origin 316 // redirects. 317 bool HadCrossOriginRedirects(); 318 319 // Principal of the currently playing video resource. Anything accessing the 320 // image container of this element must have a principal that subsumes this 321 // principal. If there are no live video tracks but content has been rendered 322 // to the image container, we return the last video principal we had. Should 323 // the image container be empty with no live video tracks, we return nullptr. 324 already_AddRefed<nsIPrincipal> GetCurrentVideoPrincipal(); 325 326 // called to notify that the principal of the decoder's media resource has 327 // changed. 328 void NotifyDecoderPrincipalChanged() final; 329 330 void GetEMEInfo(dom::EMEDebugInfo& aInfo); 331 332 // Update the visual size of the media. Called from the decoder on the 333 // main thread when/if the size changes. 334 virtual void UpdateMediaSize(const nsIntSize& aSize); 335 // Like UpdateMediaSize, but only updates the size if no size has yet 336 // been set. 337 void UpdateInitialMediaSize(const nsIntSize& aSize); 338 339 void Invalidate(bool aImageSizeChanged, Maybe<nsIntSize>& aNewIntrinsicSize, 340 bool aForceInvalidate) override; 341 342 // Returns the CanPlayStatus indicating if we can handle the 343 // full MIME type including the optional codecs parameter. 344 static CanPlayStatus GetCanPlay(const nsAString& aType, 345 DecoderDoctorDiagnostics* aDiagnostics); 346 347 /** 348 * Called when a child source element is added to this media element. This 349 * may queue a task to run the select resource algorithm if appropriate. 350 */ 351 void NotifyAddedSource(); 352 353 /** 354 * Called when there's been an error fetching the resource. This decides 355 * whether it's appropriate to fire an error event. 356 */ 357 void NotifyLoadError(const nsACString& aErrorDetails = nsCString()); 358 359 /** 360 * Called by one of our associated MediaTrackLists (audio/video) when an 361 * AudioTrack is enabled or a VideoTrack is selected. 362 */ 363 void NotifyMediaTrackEnabled(dom::MediaTrack* aTrack); 364 365 /** 366 * Called by one of our associated MediaTrackLists (audio/video) when an 367 * AudioTrack is disabled or a VideoTrack is unselected. 368 */ 369 void NotifyMediaTrackDisabled(dom::MediaTrack* aTrack); 370 371 /** 372 * Returns the current load ID. Asynchronous events store the ID that was 373 * current when they were enqueued, and if it has changed when they come to 374 * fire, they consider themselves cancelled, and don't fire. 375 */ GetCurrentLoadID()376 uint32_t GetCurrentLoadID() { return mCurrentLoadID; } 377 378 /** 379 * Returns the load group for this media element's owner document. 380 * XXX XBL2 issue. 381 */ 382 already_AddRefed<nsILoadGroup> GetDocumentLoadGroup(); 383 384 /** 385 * Returns true if the media has played or completed a seek. 386 * Used by video frame to determine whether to paint the poster. 387 */ GetPlayedOrSeeked()388 bool GetPlayedOrSeeked() const { return mHasPlayedOrSeeked; } 389 390 nsresult CopyInnerTo(Element* aDest); 391 392 /** 393 * Sets the Accept header on the HTTP channel to the required 394 * video or audio MIME types. 395 */ 396 virtual nsresult SetAcceptHeader(nsIHttpChannel* aChannel) = 0; 397 398 /** 399 * Sets the required request headers on the HTTP channel for 400 * video or audio requests. 401 */ 402 void SetRequestHeaders(nsIHttpChannel* aChannel); 403 404 /** 405 * Asynchronously awaits a stable state, whereupon aRunnable runs on the main 406 * thread. This adds an event which run aRunnable to the appshell's list of 407 * sections synchronous the next time control returns to the event loop. 408 */ 409 void RunInStableState(nsIRunnable* aRunnable); 410 411 /** 412 * Fires a timeupdate event. If aPeriodic is true, the event will only 413 * be fired if we've not fired a timeupdate event (for any reason) in the 414 * last 250ms, as required by the spec when the current time is periodically 415 * increasing during playback. 416 */ 417 void FireTimeUpdate(bool aPeriodic) final; 418 419 // WebIDL 420 421 MediaError* GetError() const; 422 GetSrc(nsAString & aSrc)423 void GetSrc(nsAString& aSrc) { GetURIAttr(nsGkAtoms::src, nullptr, aSrc); } SetSrc(const nsAString & aSrc,ErrorResult & aError)424 void SetSrc(const nsAString& aSrc, ErrorResult& aError) { 425 SetHTMLAttr(nsGkAtoms::src, aSrc, aError); 426 } SetSrc(const nsAString & aSrc,nsIPrincipal * aTriggeringPrincipal,ErrorResult & aError)427 void SetSrc(const nsAString& aSrc, nsIPrincipal* aTriggeringPrincipal, 428 ErrorResult& aError) { 429 SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError); 430 } 431 432 void GetCurrentSrc(nsAString& aCurrentSrc); 433 GetCrossOrigin(nsAString & aResult)434 void GetCrossOrigin(nsAString& aResult) { 435 // Null for both missing and invalid defaults is ok, since we 436 // always parse to an enum value, so we don't need an invalid 437 // default, and we _want_ the missing default to be null. 438 GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult); 439 } SetCrossOrigin(const nsAString & aCrossOrigin,ErrorResult & aError)440 void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError) { 441 SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError); 442 } 443 NetworkState()444 uint16_t NetworkState() const { return mNetworkState; } 445 446 void NotifyXPCOMShutdown() final; 447 448 // Called by media decoder when the audible state changed or when input is 449 // a media stream. 450 void SetAudibleState(bool aAudible) final; 451 452 // Notify agent when the MediaElement changes its audible state. 453 void NotifyAudioPlaybackChanged(AudibleChangedReasons aReason); 454 GetPreload(nsAString & aValue)455 void GetPreload(nsAString& aValue) { 456 if (mSrcAttrStream) { 457 nsGkAtoms::none->ToString(aValue); 458 return; 459 } 460 GetEnumAttr(nsGkAtoms::preload, nullptr, aValue); 461 } SetPreload(const nsAString & aValue,ErrorResult & aRv)462 void SetPreload(const nsAString& aValue, ErrorResult& aRv) { 463 if (mSrcAttrStream) { 464 return; 465 } 466 SetHTMLAttr(nsGkAtoms::preload, aValue, aRv); 467 } 468 469 already_AddRefed<TimeRanges> Buffered() const; 470 471 void Load(); 472 473 void CanPlayType(const nsAString& aType, nsAString& aResult); 474 ReadyState()475 uint16_t ReadyState() const { return mReadyState; } 476 477 bool Seeking() const; 478 479 double CurrentTime() const; 480 481 void SetCurrentTime(double aCurrentTime, ErrorResult& aRv); SetCurrentTime(double aCurrentTime)482 void SetCurrentTime(double aCurrentTime) { 483 SetCurrentTime(aCurrentTime, IgnoreErrors()); 484 } 485 486 void FastSeek(double aTime, ErrorResult& aRv); 487 488 already_AddRefed<Promise> SeekToNextFrame(ErrorResult& aRv); 489 490 double Duration() const; 491 HasAudio()492 bool HasAudio() const { return mMediaInfo.HasAudio(); } 493 IsVideo()494 virtual bool IsVideo() const { return false; } 495 HasVideo()496 bool HasVideo() const { return mMediaInfo.HasVideo(); } 497 IsEncrypted()498 bool IsEncrypted() const { return mIsEncrypted; } 499 Paused()500 bool Paused() const { return mPaused; } 501 DefaultPlaybackRate()502 double DefaultPlaybackRate() const { 503 if (mSrcAttrStream) { 504 return 1.0; 505 } 506 return mDefaultPlaybackRate; 507 } 508 509 void SetDefaultPlaybackRate(double aDefaultPlaybackRate, ErrorResult& aRv); 510 PlaybackRate()511 double PlaybackRate() const { 512 if (mSrcAttrStream) { 513 return 1.0; 514 } 515 return mPlaybackRate; 516 } 517 518 void SetPlaybackRate(double aPlaybackRate, ErrorResult& aRv); 519 520 already_AddRefed<TimeRanges> Played(); 521 522 already_AddRefed<TimeRanges> Seekable() const; 523 524 bool Ended(); 525 Autoplay()526 bool Autoplay() const { return GetBoolAttr(nsGkAtoms::autoplay); } 527 SetAutoplay(bool aValue,ErrorResult & aRv)528 void SetAutoplay(bool aValue, ErrorResult& aRv) { 529 SetHTMLBoolAttr(nsGkAtoms::autoplay, aValue, aRv); 530 } 531 Loop()532 bool Loop() const { return GetBoolAttr(nsGkAtoms::loop); } 533 SetLoop(bool aValue,ErrorResult & aRv)534 void SetLoop(bool aValue, ErrorResult& aRv) { 535 SetHTMLBoolAttr(nsGkAtoms::loop, aValue, aRv); 536 } 537 538 already_AddRefed<Promise> Play(ErrorResult& aRv); Play()539 void Play() { 540 IgnoredErrorResult dummy; 541 RefPtr<Promise> toBeIgnored = Play(dummy); 542 } 543 544 void Pause(ErrorResult& aRv); Pause()545 void Pause() { Pause(IgnoreErrors()); } 546 Controls()547 bool Controls() const { return GetBoolAttr(nsGkAtoms::controls); } 548 SetControls(bool aValue,ErrorResult & aRv)549 void SetControls(bool aValue, ErrorResult& aRv) { 550 SetHTMLBoolAttr(nsGkAtoms::controls, aValue, aRv); 551 } 552 Volume()553 double Volume() const { return mVolume; } 554 555 void SetVolume(double aVolume, ErrorResult& aRv); 556 Muted()557 bool Muted() const { return mMuted & MUTED_BY_CONTENT; } 558 void SetMuted(bool aMuted); 559 DefaultMuted()560 bool DefaultMuted() const { return GetBoolAttr(nsGkAtoms::muted); } 561 SetDefaultMuted(bool aMuted,ErrorResult & aRv)562 void SetDefaultMuted(bool aMuted, ErrorResult& aRv) { 563 SetHTMLBoolAttr(nsGkAtoms::muted, aMuted, aRv); 564 } 565 MozAllowCasting()566 bool MozAllowCasting() const { return mAllowCasting; } 567 SetMozAllowCasting(bool aShow)568 void SetMozAllowCasting(bool aShow) { mAllowCasting = aShow; } 569 MozIsCasting()570 bool MozIsCasting() const { return mIsCasting; } 571 SetMozIsCasting(bool aShow)572 void SetMozIsCasting(bool aShow) { mIsCasting = aShow; } 573 574 // Returns whether a call to Play() would be rejected with NotAllowedError. 575 // This assumes "worst case" for unknowns. So if prompting for permission is 576 // enabled and no permission is stored, this behaves as if the user would 577 // opt to block. 578 bool AllowedToPlay() const; 579 580 already_AddRefed<MediaSource> GetMozMediaSourceObject() const; 581 582 // Returns a promise which will be resolved after collecting debugging 583 // data from decoder/reader/MDSM. Used for debugging purposes. 584 already_AddRefed<Promise> MozRequestDebugInfo(ErrorResult& aRv); 585 586 // Enables DecoderDoctorLogger logging. Used for debugging purposes. 587 static void MozEnableDebugLog(const GlobalObject&); 588 589 // Returns a promise which will be resolved after collecting debugging 590 // log associated with this element. Used for debugging purposes. 591 already_AddRefed<Promise> MozRequestDebugLog(ErrorResult& aRv); 592 593 // For use by mochitests. Enabling pref "media.test.video-suspend" 594 void SetVisible(bool aVisible); 595 596 // For use by mochitests. Enabling pref "media.test.video-suspend" 597 bool HasSuspendTaint() const; 598 599 // For use by mochitests. 600 bool IsVideoDecodingSuspended() const; 601 602 // For use by mochitests only. 603 bool IsVisible() const; 604 605 // Synchronously, return the next video frame and mark the element unable to 606 // participate in decode suspending. 607 // 608 // This function is synchronous for cases where decoding has been suspended 609 // and JS needs a frame to use in, eg., nsLayoutUtils::SurfaceFromElement() 610 // via drawImage(). 611 already_AddRefed<layers::Image> GetCurrentImage(); 612 613 already_AddRefed<DOMMediaStream> GetSrcObject() const; 614 void SetSrcObject(DOMMediaStream& aValue); 615 void SetSrcObject(DOMMediaStream* aValue); 616 MozPreservesPitch()617 bool MozPreservesPitch() const { return mPreservesPitch; } 618 void SetMozPreservesPitch(bool aPreservesPitch); 619 620 MediaKeys* GetMediaKeys() const; 621 622 already_AddRefed<Promise> SetMediaKeys(MediaKeys* mediaKeys, 623 ErrorResult& aRv); 624 625 mozilla::dom::EventHandlerNonNull* GetOnencrypted(); 626 void SetOnencrypted(mozilla::dom::EventHandlerNonNull* aCallback); 627 628 mozilla::dom::EventHandlerNonNull* GetOnwaitingforkey(); 629 void SetOnwaitingforkey(mozilla::dom::EventHandlerNonNull* aCallback); 630 631 void DispatchEncrypted(const nsTArray<uint8_t>& aInitData, 632 const nsAString& aInitDataType) override; 633 634 bool IsEventAttributeNameInternal(nsAtom* aName) override; 635 636 bool ContainsRestrictedContent(); 637 638 void NotifyWaitingForKey() override; 639 640 already_AddRefed<DOMMediaStream> CaptureAudio(ErrorResult& aRv, 641 MediaTrackGraph* aGraph); 642 643 already_AddRefed<DOMMediaStream> MozCaptureStream(ErrorResult& aRv); 644 645 already_AddRefed<DOMMediaStream> MozCaptureStreamUntilEnded(ErrorResult& aRv); 646 MozAudioCaptured()647 bool MozAudioCaptured() const { return mAudioCaptured; } 648 649 void MozGetMetadata(JSContext* aCx, JS::MutableHandle<JSObject*> aResult, 650 ErrorResult& aRv); 651 652 double MozFragmentEnd(); 653 654 AudioTrackList* AudioTracks(); 655 656 VideoTrackList* VideoTracks(); 657 658 TextTrackList* GetTextTracks(); 659 660 already_AddRefed<TextTrack> AddTextTrack(TextTrackKind aKind, 661 const nsAString& aLabel, 662 const nsAString& aLanguage); 663 AddTextTrack(TextTrack * aTextTrack)664 void AddTextTrack(TextTrack* aTextTrack) { 665 GetOrCreateTextTrackManager()->AddTextTrack(aTextTrack); 666 } 667 668 void RemoveTextTrack(TextTrack* aTextTrack, bool aPendingListOnly = false) { 669 if (mTextTrackManager) { 670 mTextTrackManager->RemoveTextTrack(aTextTrack, aPendingListOnly); 671 } 672 } 673 NotifyCueAdded(TextTrackCue & aCue)674 void NotifyCueAdded(TextTrackCue& aCue) { 675 if (mTextTrackManager) { 676 mTextTrackManager->NotifyCueAdded(aCue); 677 } 678 } NotifyCueRemoved(TextTrackCue & aCue)679 void NotifyCueRemoved(TextTrackCue& aCue) { 680 if (mTextTrackManager) { 681 mTextTrackManager->NotifyCueRemoved(aCue); 682 } 683 } NotifyCueUpdated(TextTrackCue * aCue)684 void NotifyCueUpdated(TextTrackCue* aCue) { 685 if (mTextTrackManager) { 686 mTextTrackManager->NotifyCueUpdated(aCue); 687 } 688 } 689 690 void NotifyCueDisplayStatesChanged(); 691 IsBlessed()692 bool IsBlessed() const { return mIsBlessed; } 693 694 // A method to check whether we are currently playing. 695 bool IsCurrentlyPlaying() const; 696 697 // Returns true if the media element is being destroyed. Used in 698 // dormancy checks to prevent dormant processing for an element 699 // that will soon be gone. 700 bool IsBeingDestroyed(); 701 702 void OnVisibilityChange(Visibility aNewVisibility); 703 704 // Begin testing only methods 705 float ComputedVolume() const; 706 bool ComputedMuted() const; 707 708 // Return true if the media has been suspended media due to an inactive 709 // document or prohibiting by the docshell. 710 bool IsSuspendedByInactiveDocOrDocShell() const; 711 // End testing only methods 712 713 void SetMediaInfo(const MediaInfo& aInfo); 714 715 AbstractThread* AbstractMainThread() const final; 716 717 // Telemetry: to record the usage of a {visible / invisible} video element as 718 // the source of {drawImage(), createPattern(), createImageBitmap() and 719 // captureStream()} APIs. 720 enum class CallerAPI { 721 DRAW_IMAGE, 722 CREATE_PATTERN, 723 CREATE_IMAGEBITMAP, 724 CAPTURE_STREAM, 725 }; 726 void MarkAsContentSource(CallerAPI aAPI); 727 728 Document* GetDocument() const override; 729 730 already_AddRefed<GMPCrashHelper> CreateGMPCrashHelper() override; 731 MainThreadEventTarget()732 nsISerialEventTarget* MainThreadEventTarget() { 733 return mMainThreadEventTarget; 734 } 735 736 // Set the sink id (of the output device) that the audio will play. If aSinkId 737 // is empty the default device will be set. 738 already_AddRefed<Promise> SetSinkId(const nsAString& aSinkId, 739 ErrorResult& aRv); 740 // Get the sink id of the device that audio is being played. Initial value is 741 // empty and the default device is being used. GetSinkId(nsString & aSinkId)742 void GetSinkId(nsString& aSinkId) { 743 MOZ_ASSERT(NS_IsMainThread()); 744 aSinkId = mSink.first; 745 } 746 747 // This is used to notify MediaElementAudioSourceNode that media element is 748 // allowed to play when media element is used as a source for web audio, so 749 // that we can start AudioContext if it was not allowed to start. 750 RefPtr<GenericNonExclusivePromise> GetAllowedToPlayPromise(); 751 GetShowPosterFlag()752 bool GetShowPosterFlag() const { return mShowPoster; } 753 754 bool IsAudible() const; 755 756 protected: 757 virtual ~HTMLMediaElement(); 758 759 class AudioChannelAgentCallback; 760 class ChannelLoader; 761 class ErrorSink; 762 class MediaElementTrackSource; 763 class MediaLoadListener; 764 class MediaStreamRenderer; 765 class MediaStreamTrackListener; 766 class FirstFrameListener; 767 class ShutdownObserver; 768 class MediaControlEventListener; 769 770 MediaDecoderOwner::NextFrameStatus NextFrameStatus(); 771 772 void SetDecoder(MediaDecoder* aDecoder); 773 774 void PlayInternal(bool aHandlingUserInput); 775 776 /** Use this method to change the mReadyState member, so required 777 * events can be fired. 778 */ 779 void ChangeReadyState(nsMediaReadyState aState); 780 781 /** 782 * Use this method to change the mNetworkState member, so required 783 * actions will be taken during the transition. 784 */ 785 void ChangeNetworkState(nsMediaNetworkState aState); 786 787 /** 788 * The MediaElement will be responsible for creating and releasing the audio 789 * wakelock depending on the playing and audible state. 790 */ 791 virtual void WakeLockRelease(); 792 virtual void UpdateWakeLock(); 793 794 void CreateAudioWakeLockIfNeeded(); 795 void ReleaseAudioWakeLockIfExists(); 796 RefPtr<WakeLock> mWakeLock; 797 798 /** 799 * Logs a warning message to the web console to report various failures. 800 * aMsg is the localized message identifier, aParams is the parameters to 801 * be substituted into the localized message, and aParamCount is the number 802 * of parameters in aParams. 803 */ 804 void ReportLoadError(const char* aMsg, const nsTArray<nsString>& aParams = 805 nsTArray<nsString>()); 806 807 /** 808 * Log message to web console. 809 */ 810 void ReportToConsole( 811 uint32_t aErrorFlags, const char* aMsg, 812 const nsTArray<nsString>& aParams = nsTArray<nsString>()) const; 813 814 /** 815 * Changes mHasPlayedOrSeeked to aValue. If mHasPlayedOrSeeked changes 816 * we'll force a reflow so that the video frame gets reflowed to reflect 817 * the poster hiding or showing immediately. 818 */ 819 void SetPlayedOrSeeked(bool aValue); 820 821 /** 822 * Initialize the media element for playback of aStream 823 */ 824 void SetupSrcMediaStreamPlayback(DOMMediaStream* aStream); 825 /** 826 * Stop playback on mSrcStream. 827 */ 828 void EndSrcMediaStreamPlayback(); 829 /** 830 * Ensure we're playing mSrcStream if and only if we're not paused. 831 */ 832 enum { REMOVING_SRC_STREAM = 0x1 }; 833 void UpdateSrcMediaStreamPlaying(uint32_t aFlags = 0); 834 835 /** 836 * Ensure currentTime progresses if and only if we're potentially playing 837 * mSrcStream. Called by the watch manager while we're playing mSrcStream, and 838 * one of the inputs to the potentially playing algorithm changes. 839 */ 840 void UpdateSrcStreamPotentiallyPlaying(); 841 842 /** 843 * mSrcStream's graph's CurrentTime() has been updated. It might be time to 844 * fire "timeupdate". 845 */ 846 void UpdateSrcStreamTime(); 847 848 /** 849 * Called after a tail dispatch when playback of mSrcStream ended, to comply 850 * with the spec where we must start reporting true for the ended attribute 851 * after the event loop returns to step 1. A MediaStream could otherwise be 852 * manipulated to end a HTMLMediaElement synchronously. 853 */ 854 void UpdateSrcStreamReportPlaybackEnded(); 855 856 /** 857 * Called by our DOMMediaStream::TrackListener when a new MediaStreamTrack has 858 * been added to the playback stream of |mSrcStream|. 859 */ 860 void NotifyMediaStreamTrackAdded(const RefPtr<MediaStreamTrack>& aTrack); 861 862 /** 863 * Called by our DOMMediaStream::TrackListener when a MediaStreamTrack in 864 * |mSrcStream|'s playback stream has ended. 865 */ 866 void NotifyMediaStreamTrackRemoved(const RefPtr<MediaStreamTrack>& aTrack); 867 868 /** 869 * Convenience method to get in a single list all enabled AudioTracks and, if 870 * this is a video element, the selected VideoTrack. 871 */ 872 void GetAllEnabledMediaTracks(nsTArray<RefPtr<MediaTrack>>& aTracks); 873 874 /** 875 * Enables or disables all tracks forwarded from mSrcStream to all 876 * OutputMediaStreams. We do this for muting the tracks when pausing, 877 * and unmuting when playing the media element again. 878 */ 879 void SetCapturedOutputStreamsEnabled(bool aEnabled); 880 881 /** 882 * Returns true if output tracks should be muted, based on the state of this 883 * media element. 884 */ 885 enum class OutputMuteState { Muted, Unmuted }; 886 OutputMuteState OutputTracksMuted(); 887 888 /** 889 * Sets the muted state of all output track sources. They are muted when we're 890 * paused and unmuted otherwise. 891 */ 892 void UpdateOutputTracksMuting(); 893 894 /** 895 * Create a new MediaStreamTrack for the TrackSource corresponding to aTrack 896 * and add it to the DOMMediaStream in aOutputStream. This automatically sets 897 * the output track to enabled or disabled depending on our current playing 898 * state. 899 */ 900 enum class AddTrackMode { ASYNC, SYNC }; 901 void AddOutputTrackSourceToOutputStream( 902 MediaElementTrackSource* aSource, OutputMediaStream& aOutputStream, 903 AddTrackMode aMode = AddTrackMode::ASYNC); 904 905 /** 906 * Creates output track sources when this media element is captured, tracks 907 * exist, playback is not ended and readyState is >= HAVE_METADATA. 908 */ 909 void UpdateOutputTrackSources(); 910 911 /** 912 * Returns an DOMMediaStream containing the played contents of this 913 * element. When aBehavior is FINISH_WHEN_ENDED, when this element ends 914 * playback we will finish the stream and not play any more into it. When 915 * aType is CONTINUE_WHEN_ENDED, ending playback does not finish the stream. 916 * The stream will never finish. 917 * 918 * When aType is CAPTURE_AUDIO, we stop playout of audio and instead route it 919 * to the DOMMediaStream. Volume and mute state will be applied to the audio 920 * reaching the stream. No video tracks will be captured in this case. 921 */ 922 already_AddRefed<DOMMediaStream> CaptureStreamInternal( 923 StreamCaptureBehavior aFinishBehavior, 924 StreamCaptureType aStreamCaptureType, MediaTrackGraph* aGraph); 925 926 /** 927 * Initialize a decoder as a clone of an existing decoder in another 928 * element. 929 * mLoadingSrc must already be set. 930 */ 931 nsresult InitializeDecoderAsClone(ChannelMediaDecoder* aOriginal); 932 933 /** 934 * Call Load() and FinishDecoderSetup() on the decoder. It also handle 935 * resource cloning if DecoderType is ChannelMediaDecoder. 936 */ 937 template <typename DecoderType, typename... LoadArgs> 938 nsresult SetupDecoder(DecoderType* aDecoder, LoadArgs&&... aArgs); 939 940 /** 941 * Initialize a decoder to load the given channel. The decoder's stream 942 * listener is returned via aListener. 943 * mLoadingSrc must already be set. 944 */ 945 nsresult InitializeDecoderForChannel(nsIChannel* aChannel, 946 nsIStreamListener** aListener); 947 948 /** 949 * Finish setting up the decoder after Load() has been called on it. 950 * Called by InitializeDecoderForChannel/InitializeDecoderAsClone. 951 */ 952 nsresult FinishDecoderSetup(MediaDecoder* aDecoder); 953 954 /** 955 * Call this after setting up mLoadingSrc and mDecoder. 956 */ 957 void AddMediaElementToURITable(); 958 /** 959 * Call this before modifying mLoadingSrc. 960 */ 961 void RemoveMediaElementFromURITable(); 962 /** 963 * Call this to find a media element with the same NodePrincipal and 964 * mLoadingSrc set to aURI, and with a decoder on which Load() has been 965 * called. 966 */ 967 HTMLMediaElement* LookupMediaElementURITable(nsIURI* aURI); 968 969 /** 970 * Shutdown and clear mDecoder and maintain associated invariants. 971 */ 972 void ShutdownDecoder(); 973 /** 974 * Execute the initial steps of the load algorithm that ensure existing 975 * loads are aborted, the element is emptied, and a new load ID is 976 * created. 977 */ 978 void AbortExistingLoads(); 979 980 /** 981 * This is the dedicated media source failure steps. 982 * Called when all potential resources are exhausted. Changes network 983 * state to NETWORK_NO_SOURCE, and sends error event with code 984 * MEDIA_ERR_SRC_NOT_SUPPORTED. 985 */ 986 void NoSupportedMediaSourceError( 987 const nsACString& aErrorDetails = nsCString()); 988 989 /** 990 * Per spec, Failed with elements: Queue a task, using the DOM manipulation 991 * task source, to fire a simple event named error at the candidate element. 992 * So dispatch |QueueLoadFromSourceTask| to main thread to make sure the task 993 * will be executed later than loadstart event. 994 */ 995 void DealWithFailedElement(nsIContent* aSourceElement); 996 997 /** 998 * Attempts to load resources from the <source> children. This is a 999 * substep of the resource selection algorithm. Do not call this directly, 1000 * call QueueLoadFromSourceTask() instead. 1001 */ 1002 void LoadFromSourceChildren(); 1003 1004 /** 1005 * Asynchronously awaits a stable state, and then causes 1006 * LoadFromSourceChildren() to be called on the main threads' event loop. 1007 */ 1008 void QueueLoadFromSourceTask(); 1009 1010 /** 1011 * Runs the media resource selection algorithm. 1012 */ 1013 void SelectResource(); 1014 1015 /** 1016 * A wrapper function that allows us to cleanly reset flags after a call 1017 * to SelectResource() 1018 */ 1019 void SelectResourceWrapper(); 1020 1021 /** 1022 * Asynchronously awaits a stable state, and then causes SelectResource() 1023 * to be run on the main thread's event loop. 1024 */ 1025 void QueueSelectResourceTask(); 1026 1027 /** 1028 * When loading a new source on an existing media element, make sure to reset 1029 * everything that is accessible using the media element API. 1030 */ 1031 void ResetState(); 1032 1033 /** 1034 * The resource-fetch algorithm step of the load algorithm. 1035 */ 1036 MediaResult LoadResource(); 1037 1038 /** 1039 * Selects the next <source> child from which to load a resource. Called 1040 * during the resource selection algorithm. Stores the return value in 1041 * mSourceLoadCandidate before returning. 1042 */ 1043 Element* GetNextSource(); 1044 1045 /** 1046 * Changes mDelayingLoadEvent, and will call BlockOnLoad()/UnblockOnLoad() 1047 * on the owning document, so it can delay the load event firing. 1048 */ 1049 void ChangeDelayLoadStatus(bool aDelay); 1050 1051 /** 1052 * If we suspended downloading after the first frame, unsuspend now. 1053 */ 1054 void StopSuspendingAfterFirstFrame(); 1055 1056 /** 1057 * Called when our channel is redirected to another channel. 1058 * Updates our mChannel reference to aNewChannel. 1059 */ 1060 nsresult OnChannelRedirect(nsIChannel* aChannel, nsIChannel* aNewChannel, 1061 uint32_t aFlags); 1062 1063 /** 1064 * Call this to reevaluate whether we should be holding a self-reference. 1065 */ 1066 void AddRemoveSelfReference(); 1067 1068 /** 1069 * Called when "xpcom-shutdown" event is received. 1070 */ 1071 void NotifyShutdownEvent(); 1072 1073 /** 1074 * Possible values of the 'preload' attribute. 1075 */ 1076 enum PreloadAttrValue : uint8_t { 1077 PRELOAD_ATTR_EMPTY, // set to "" 1078 PRELOAD_ATTR_NONE, // set to "none" 1079 PRELOAD_ATTR_METADATA, // set to "metadata" 1080 PRELOAD_ATTR_AUTO // set to "auto" 1081 }; 1082 1083 /** 1084 * The preloading action to perform. These dictate how we react to the 1085 * preload attribute. See mPreloadAction. 1086 */ 1087 enum PreloadAction { 1088 PRELOAD_UNDEFINED = 0, // not determined - used only for initialization 1089 PRELOAD_NONE = 1, // do not preload 1090 PRELOAD_METADATA = 2, // preload only the metadata (and first frame) 1091 PRELOAD_ENOUGH = 3 // preload enough data to allow uninterrupted 1092 // playback 1093 }; 1094 1095 /** 1096 * The guts of Load(). Load() acts as a wrapper around this which sets 1097 * mIsDoingExplicitLoad to true so that when script calls 'load()' 1098 * preload-none will be automatically upgraded to preload-metadata. 1099 */ 1100 void DoLoad(); 1101 1102 /** 1103 * Suspends the load of mLoadingSrc, so that it can be resumed later 1104 * by ResumeLoad(). This is called when we have a media with a 'preload' 1105 * attribute value of 'none', during the resource selection algorithm. 1106 */ 1107 void SuspendLoad(); 1108 1109 /** 1110 * Resumes a previously suspended load (suspended by SuspendLoad(uri)). 1111 * Will continue running the resource selection algorithm. 1112 * Sets mPreloadAction to aAction. 1113 */ 1114 void ResumeLoad(PreloadAction aAction); 1115 1116 /** 1117 * Handle a change to the preload attribute. Should be called whenever the 1118 * value (or presence) of the preload attribute changes. The change in 1119 * attribute value may cause a change in the mPreloadAction of this 1120 * element. If there is a change then this method will initiate any 1121 * behaviour that is necessary to implement the action. 1122 */ 1123 void UpdatePreloadAction(); 1124 1125 /** 1126 * Fire progress events if needed according to the time and byte constraints 1127 * outlined in the specification. aHaveNewProgress is true if progress has 1128 * just been detected. Otherwise the method is called as a result of the 1129 * progress timer. 1130 */ 1131 void CheckProgress(bool aHaveNewProgress); 1132 static void ProgressTimerCallback(nsITimer* aTimer, void* aClosure); 1133 /** 1134 * Start timer to update download progress. 1135 */ 1136 void StartProgressTimer(); 1137 /** 1138 * Start sending progress and/or stalled events. 1139 */ 1140 void StartProgress(); 1141 /** 1142 * Stop progress information timer and events. 1143 */ 1144 void StopProgress(); 1145 1146 /** 1147 * Dispatches an error event to a child source element. 1148 */ 1149 void DispatchAsyncSourceError(nsIContent* aSourceElement); 1150 1151 /** 1152 * Resets the media element for an error condition as per aErrorCode. 1153 * aErrorCode must be one of WebIDL HTMLMediaElement error codes. 1154 */ 1155 void Error(uint16_t aErrorCode, 1156 const nsACString& aErrorDetails = nsCString()); 1157 1158 /** 1159 * Returns the URL spec of the currentSrc. 1160 **/ 1161 void GetCurrentSpec(nsCString& aString); 1162 1163 /** 1164 * Process any media fragment entries in the URI 1165 */ 1166 void ProcessMediaFragmentURI(); 1167 1168 /** 1169 * Mute or unmute the audio and change the value that the |muted| map. 1170 */ 1171 void SetMutedInternal(uint32_t aMuted); 1172 /** 1173 * Update the volume of the output audio stream to match the element's 1174 * current mMuted/mVolume/mAudioChannelFaded state. 1175 */ 1176 void SetVolumeInternal(); 1177 1178 /** 1179 * Suspend or resume element playback and resource download. When we suspend 1180 * playback, event delivery would also be suspended (and events queued) until 1181 * the element is resumed. 1182 */ 1183 void SuspendOrResumeElement(bool aSuspendElement); 1184 1185 // Get the HTMLMediaElement object if the decoder is being used from an 1186 // HTML media element, and null otherwise. GetMediaElement()1187 HTMLMediaElement* GetMediaElement() final { return this; } 1188 1189 // Return true if decoding should be paused GetPaused()1190 bool GetPaused() final { return Paused(); } 1191 1192 /** 1193 * Video has been playing while hidden and, if feature was enabled, would 1194 * trigger suspending decoder. 1195 * Used to track hidden-video-decode-suspend telemetry. 1196 */ 1197 static void VideoDecodeSuspendTimerCallback(nsITimer* aTimer, void* aClosure); 1198 /** 1199 * Video is now both: playing and hidden. 1200 * Used to track hidden-video telemetry. 1201 */ 1202 void HiddenVideoStart(); 1203 /** 1204 * Video is not playing anymore and/or has become visible. 1205 * Used to track hidden-video telemetry. 1206 */ 1207 void HiddenVideoStop(); 1208 1209 void ReportTelemetry(); 1210 1211 // Seeks to aTime seconds. aSeekType can be Exact to seek to exactly the 1212 // seek target, or PrevSyncPoint if a quicker but less precise seek is 1213 // desired, and we'll seek to the sync point (keyframe and/or start of the 1214 // next block of audio samples) preceeding seek target. 1215 void Seek(double aTime, SeekTarget::Type aSeekType, ErrorResult& aRv); 1216 1217 // Update the audio channel playing state 1218 void UpdateAudioChannelPlayingState(); 1219 1220 // Adds to the element's list of pending text tracks each text track 1221 // in the element's list of text tracks whose text track mode is not disabled 1222 // and whose text track readiness state is loading. 1223 void PopulatePendingTextTrackList(); 1224 1225 // Gets a reference to the MediaElement's TextTrackManager. If the 1226 // MediaElement doesn't yet have one then it will create it. 1227 TextTrackManager* GetOrCreateTextTrackManager(); 1228 1229 // Recomputes ready state and fires events as necessary based on current 1230 // state. 1231 void UpdateReadyStateInternal(); 1232 1233 // Create or destroy the captured stream. 1234 void AudioCaptureTrackChange(bool aCapture); 1235 1236 // If the network state is empty and then we would trigger DoLoad(). 1237 void MaybeDoLoad(); 1238 1239 // Anything we need to check after played success and not related with spec. 1240 void UpdateCustomPolicyAfterPlayed(); 1241 1242 // Returns a StreamCaptureType populated with the right bits, depending on the 1243 // tracks this HTMLMediaElement has. 1244 StreamCaptureType CaptureTypeForElement(); 1245 1246 // True if this element can be captured, false otherwise. 1247 bool CanBeCaptured(StreamCaptureType aCaptureType); 1248 1249 class nsAsyncEventRunner; 1250 class nsNotifyAboutPlayingRunner; 1251 class nsResolveOrRejectPendingPlayPromisesRunner; 1252 using nsGenericHTMLElement::DispatchEvent; 1253 // For nsAsyncEventRunner. 1254 nsresult DispatchEvent(const nsAString& aName); 1255 1256 // This method moves the mPendingPlayPromises into a temperate object. So the 1257 // mPendingPlayPromises is cleared after this method call. 1258 nsTArray<RefPtr<PlayPromise>> TakePendingPlayPromises(); 1259 1260 // This method snapshots the mPendingPlayPromises by TakePendingPlayPromises() 1261 // and queues a task to resolve them. 1262 void AsyncResolvePendingPlayPromises(); 1263 1264 // This method snapshots the mPendingPlayPromises by TakePendingPlayPromises() 1265 // and queues a task to reject them. 1266 void AsyncRejectPendingPlayPromises(nsresult aError); 1267 1268 // This method snapshots the mPendingPlayPromises by TakePendingPlayPromises() 1269 // and queues a task to resolve them also to dispatch a "playing" event. 1270 void NotifyAboutPlaying(); 1271 1272 already_AddRefed<Promise> CreateDOMPromise(ErrorResult& aRv) const; 1273 1274 // Pass information for deciding the video decode mode to decoder. 1275 void NotifyDecoderActivityChanges() const; 1276 1277 // Constructs an AudioTrack in mAudioTrackList if aInfo reports that audio is 1278 // available, and a VideoTrack in mVideoTrackList if aInfo reports that video 1279 // is available. 1280 void ConstructMediaTracks(const MediaInfo* aInfo); 1281 1282 // Removes all MediaTracks from mAudioTrackList and mVideoTrackList and fires 1283 // "removetrack" on the lists accordingly. 1284 // Note that by spec, this should not fire "removetrack". However, it appears 1285 // other user agents do, per 1286 // https://wpt.fyi/results/media-source/mediasource-avtracks.html. 1287 void RemoveMediaTracks(); 1288 1289 // Mark the decoder owned by the element as tainted so that the 1290 // suspend-video-decoder is disabled. 1291 void MarkAsTainted(); 1292 1293 virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName, 1294 const nsAttrValue* aValue, 1295 const nsAttrValue* aOldValue, 1296 nsIPrincipal* aMaybeScriptedPrincipal, 1297 bool aNotify) override; 1298 virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName, 1299 const nsAttrValueOrString& aValue, 1300 bool aNotify) override; 1301 1302 bool DetachExistingMediaKeys(); 1303 bool TryRemoveMediaKeysAssociation(); 1304 void RemoveMediaKeys(); 1305 bool AttachNewMediaKeys(); 1306 bool TryMakeAssociationWithCDM(CDMProxy* aProxy); 1307 void MakeAssociationWithCDMResolved(); 1308 void SetCDMProxyFailure(const MediaResult& aResult); 1309 void ResetSetMediaKeysTempVariables(); 1310 1311 void PauseIfShouldNotBePlaying(); 1312 1313 WatchManager<HTMLMediaElement> mWatchManager; 1314 1315 // Update the silence range of the audio track when the audible status of 1316 // silent audio track changes or seeking to the new position where the audio 1317 // track is silent. 1318 void UpdateAudioTrackSilenceRange(bool aAudible); 1319 1320 // When silent audio track becomes audible or seeking to new place, we would 1321 // end the current silence range and accumulate it to the total silence 1322 // proportion of audio track and update current silence range. 1323 void AccumulateAudioTrackSilence(); 1324 1325 // True when the media element's audio track is containing silence now. 1326 bool IsAudioTrackCurrentlySilent() const; 1327 1328 // Calculate the audio track silence proportion and then report the telemetry 1329 // result. we would report the result when decoder is destroyed. 1330 void ReportAudioTrackSilenceProportionTelemetry(); 1331 1332 // When the play is not allowed, dispatch related events which are used for 1333 // testing or changing control UI. 1334 void DispatchEventsWhenPlayWasNotAllowed(); 1335 1336 // When the doc is blocked permanantly, we would dispatch event to notify 1337 // front-end side to show blocking icon. 1338 void MaybeNotifyAutoplayBlocked(); 1339 1340 // When playing state change, we have to notify MediaControl in the chrome 1341 // process in order to keep its playing state correct. 1342 void NotifyMediaControlPlaybackStateChanged(); 1343 1344 // After media has been paused, trigger a timer to stop listening to the media 1345 // control key events. 1346 void CreateStopMediaControlTimerIfNeeded(); 1347 static void StopMediaControlTimerCallback(nsITimer* aTimer, void* aClosure); 1348 1349 // Clear the timer when we want to continue listening to the media control 1350 // key events. 1351 void ClearStopMediaControlTimerIfNeeded(); 1352 1353 // This function is used to update the status of media control when the media 1354 // changes its status of being used in the Picture-in-Picture mode. 1355 void UpdateMediaControlAfterPictureInPictureModeChanged(); 1356 1357 // The current decoder. Load() has been called on this decoder. 1358 // At most one of mDecoder and mSrcStream can be non-null. 1359 RefPtr<MediaDecoder> mDecoder; 1360 1361 // The DocGroup-specific nsISerialEventTarget of this HTML element on the main 1362 // thread. 1363 nsCOMPtr<nsISerialEventTarget> mMainThreadEventTarget; 1364 1365 // The DocGroup-specific AbstractThread::MainThread() of this HTML element. 1366 RefPtr<AbstractThread> mAbstractMainThread; 1367 1368 // A reference to the VideoFrameContainer which contains the current frame 1369 // of video to display. 1370 RefPtr<VideoFrameContainer> mVideoFrameContainer; 1371 1372 // Holds a reference to the MediaStream that has been set in the src 1373 // attribute. 1374 RefPtr<DOMMediaStream> mSrcAttrStream; 1375 1376 // Holds the triggering principal for the src attribute. 1377 nsCOMPtr<nsIPrincipal> mSrcAttrTriggeringPrincipal; 1378 1379 // Holds a reference to the MediaStream that we're actually playing. 1380 // At most one of mDecoder and mSrcStream can be non-null. 1381 RefPtr<DOMMediaStream> mSrcStream; 1382 1383 // The MediaStreamRenderer handles rendering of our selected video track, and 1384 // enabled audio tracks, while mSrcStream is set. 1385 RefPtr<MediaStreamRenderer> mMediaStreamRenderer; 1386 1387 // True once PlaybackEnded() is called and we're playing a MediaStream. 1388 // Reset to false if we start playing mSrcStream again. 1389 Watchable<bool> mSrcStreamPlaybackEnded = { 1390 false, "HTMLMediaElement::mSrcStreamPlaybackEnded"}; 1391 1392 // Mirrors mSrcStreamPlaybackEnded after a tail dispatch when set to true, 1393 // but may be be forced to false directly. To accomodate when an application 1394 // ends playback synchronously by manipulating mSrcStream or its tracks, 1395 // e.g., through MediaStream.removeTrack(), or MediaStreamTrack.stop(). 1396 bool mSrcStreamReportPlaybackEnded = false; 1397 1398 // Holds a reference to the stream connecting this stream to the window 1399 // capture sink. 1400 UniquePtr<MediaStreamWindowCapturer> mStreamWindowCapturer; 1401 1402 // Holds references to the DOM wrappers for the MediaStreams that we're 1403 // writing to. 1404 nsTArray<OutputMediaStream> mOutputStreams; 1405 1406 // Mapping for output tracks, from dom::MediaTrack ids to the 1407 // MediaElementTrackSource that represents the source of all corresponding 1408 // MediaStreamTracks captured from this element. 1409 nsRefPtrHashtable<nsStringHashKey, MediaElementTrackSource> 1410 mOutputTrackSources; 1411 1412 // Holds a reference to the first-frame-getting track listener attached to 1413 // mSelectedVideoStreamTrack. 1414 RefPtr<FirstFrameListener> mFirstFrameListener; 1415 // The currently selected video stream track. 1416 RefPtr<VideoStreamTrack> mSelectedVideoStreamTrack; 1417 1418 const RefPtr<ShutdownObserver> mShutdownObserver; 1419 1420 // Holds a reference to the MediaSource, if any, referenced by the src 1421 // attribute on the media element. 1422 RefPtr<MediaSource> mSrcMediaSource; 1423 1424 // Holds a reference to the MediaSource supplying data for playback. This 1425 // may either match mSrcMediaSource or come from Source element children. 1426 // This is set when and only when mLoadingSrc corresponds to an object url 1427 // that resolved to a MediaSource. 1428 RefPtr<MediaSource> mMediaSource; 1429 1430 RefPtr<ChannelLoader> mChannelLoader; 1431 1432 // Points to the child source elements, used to iterate through the children 1433 // when selecting a resource to load. This is the previous sibling of the 1434 // child considered the current 'candidate' in: 1435 // https://html.spec.whatwg.org/multipage/media.html#concept-media-load-algorithm 1436 // 1437 // mSourcePointer == nullptr, we will next try to load |GetFirstChild()|. 1438 // mSourcePointer == GetLastChild(), we've exhausted all sources, waiting 1439 // for new elements to be appended. 1440 nsCOMPtr<nsIContent> mSourcePointer; 1441 1442 // Points to the document whose load we're blocking. This is the document 1443 // we're bound to when loading starts. 1444 nsCOMPtr<Document> mLoadBlockedDoc; 1445 1446 // Contains names of events that have been raised while in the bfcache. 1447 // These events get re-dispatched when the bfcache is exited. 1448 nsTArray<nsString> mPendingEvents; 1449 1450 // Media loading flags. See: 1451 // http://www.whatwg.org/specs/web-apps/current-work/#video) 1452 nsMediaNetworkState mNetworkState = HTMLMediaElement_Binding::NETWORK_EMPTY; 1453 Watchable<nsMediaReadyState> mReadyState = { 1454 HTMLMediaElement_Binding::HAVE_NOTHING, "HTMLMediaElement::mReadyState"}; 1455 1456 enum LoadAlgorithmState { 1457 // No load algorithm instance is waiting for a source to be added to the 1458 // media in order to continue loading. 1459 NOT_WAITING, 1460 // We've run the load algorithm, and we tried all source children of the 1461 // media element, and failed to load any successfully. We're waiting for 1462 // another source element to be added to the media element, and will try 1463 // to load any such element when its added. 1464 WAITING_FOR_SOURCE 1465 }; 1466 1467 // The current media load ID. This is incremented every time we start a 1468 // new load. Async events note the ID when they're first sent, and only fire 1469 // if the ID is unchanged when they come to fire. 1470 uint32_t mCurrentLoadID = 0; 1471 1472 // Denotes the waiting state of a load algorithm instance. When the load 1473 // algorithm is waiting for a source element child to be added, this is set 1474 // to WAITING_FOR_SOURCE, otherwise it's NOT_WAITING. 1475 LoadAlgorithmState mLoadWaitStatus = NOT_WAITING; 1476 1477 // Current audio volume 1478 double mVolume = 1.0; 1479 1480 // True if the audio track is not silent. 1481 bool mIsAudioTrackAudible = false; 1482 1483 // Used to mark the start of the silence range of audio track. 1484 double mAudioTrackSilenceStartedTime = 0.0; 1485 1486 // Save all the silence ranges, all ranges would be normalized. That means 1487 // intervals won't overlap or touch each other. 1488 media::TimeIntervals mSilenceTimeRanges; 1489 1490 // True if we have calculated silence range before SeekEnd(). This attribute 1491 // would be reset after seeking completed. 1492 bool mHasAccumulatedSilenceRangeBeforeSeekEnd = false; 1493 1494 enum MutedReasons { 1495 MUTED_BY_CONTENT = 0x01, 1496 MUTED_BY_INVALID_PLAYBACK_RATE = 0x02, 1497 MUTED_BY_AUDIO_CHANNEL = 0x04, 1498 MUTED_BY_AUDIO_TRACK = 0x08 1499 }; 1500 1501 uint32_t mMuted = 0; 1502 1503 UniquePtr<const MetadataTags> mTags; 1504 1505 // URI of the resource we're attempting to load. This stores the value we 1506 // return in the currentSrc attribute. Use GetCurrentSrc() to access the 1507 // currentSrc attribute. 1508 // This is always the original URL we're trying to load --- before 1509 // redirects etc. 1510 nsCOMPtr<nsIURI> mLoadingSrc; 1511 1512 // The triggering principal for the current source. 1513 nsCOMPtr<nsIPrincipal> mLoadingSrcTriggeringPrincipal; 1514 1515 // Stores the current preload action for this element. Initially set to 1516 // PRELOAD_UNDEFINED, its value is changed by calling 1517 // UpdatePreloadAction(). 1518 PreloadAction mPreloadAction = PRELOAD_UNDEFINED; 1519 1520 // Time that the last timeupdate event was fired. Read/Write from the 1521 // main thread only. 1522 TimeStamp mTimeUpdateTime; 1523 1524 // Time that the last progress event was fired. Read/Write from the 1525 // main thread only. 1526 TimeStamp mProgressTime; 1527 1528 // Time that data was last read from the media resource. Used for 1529 // computing if the download has stalled and to rate limit progress events 1530 // when data is arriving slower than PROGRESS_MS. 1531 // Read/Write from the main thread only. 1532 TimeStamp mDataTime; 1533 1534 // Media 'currentTime' value when the last timeupdate event occurred. 1535 // Read/Write from the main thread only. 1536 double mLastCurrentTime = 0.0; 1537 1538 // Logical start time of the media resource in seconds as obtained 1539 // from any media fragments. A negative value indicates that no 1540 // fragment time has been set. Read/Write from the main thread only. 1541 double mFragmentStart = -1.0; 1542 1543 // Logical end time of the media resource in seconds as obtained 1544 // from any media fragments. A negative value indicates that no 1545 // fragment time has been set. Read/Write from the main thread only. 1546 double mFragmentEnd = -1.0; 1547 1548 // The defaultPlaybackRate attribute gives the desired speed at which the 1549 // media resource is to play, as a multiple of its intrinsic speed. 1550 double mDefaultPlaybackRate = 1.0; 1551 1552 // The playbackRate attribute gives the speed at which the media resource 1553 // plays, as a multiple of its intrinsic speed. If it is not equal to the 1554 // defaultPlaybackRate, then the implication is that the user is using a 1555 // feature such as fast forward or slow motion playback. 1556 double mPlaybackRate = 1.0; 1557 1558 // True if pitch correction is applied when playbackRate is set to a 1559 // non-intrinsic value. 1560 bool mPreservesPitch = true; 1561 1562 // Reference to the source element last returned by GetNextSource(). 1563 // This is the child source element which we're trying to load from. 1564 nsCOMPtr<nsIContent> mSourceLoadCandidate; 1565 1566 // Range of time played. 1567 RefPtr<TimeRanges> mPlayed; 1568 1569 // Timer used for updating progress events. 1570 nsCOMPtr<nsITimer> mProgressTimer; 1571 1572 // Timer used to simulate video-suspend. 1573 nsCOMPtr<nsITimer> mVideoDecodeSuspendTimer; 1574 1575 // Timer used to stop listening media control events. 1576 nsCOMPtr<nsITimer> mStopMediaControlTimer; 1577 1578 // Encrypted Media Extension media keys. 1579 RefPtr<MediaKeys> mMediaKeys; 1580 RefPtr<MediaKeys> mIncomingMediaKeys; 1581 // The dom promise is used for HTMLMediaElement::SetMediaKeys. 1582 RefPtr<DetailedPromise> mSetMediaKeysDOMPromise; 1583 // Used to indicate if the MediaKeys attaching operation is on-going or not. 1584 bool mAttachingMediaKey = false; 1585 MozPromiseRequestHolder<SetCDMPromise> mSetCDMRequest; 1586 1587 // Stores the time at the start of the current 'played' range. 1588 double mCurrentPlayRangeStart = 1.0; 1589 1590 // True if loadeddata has been fired. 1591 bool mLoadedDataFired = false; 1592 1593 // Indicates whether current playback is a result of user action 1594 // (ie. calling of the Play method), or automatic playback due to 1595 // the 'autoplay' attribute being set. A true value indicates the 1596 // latter case. 1597 // The 'autoplay' HTML attribute indicates that the video should 1598 // start playing when loaded. The 'autoplay' attribute of the object 1599 // is a mirror of the HTML attribute. These are different from this 1600 // 'mAutoplaying' flag, which indicates whether the current playback 1601 // is a result of the autoplay attribute. 1602 bool mAutoplaying = true; 1603 1604 // Playback of the video is paused either due to calling the 1605 // 'Pause' method, or playback not yet having started. 1606 Watchable<bool> mPaused = {true, "HTMLMediaElement::mPaused"}; 1607 1608 // The following two fields are here for the private storage of the builtin 1609 // video controls, and control 'casting' of the video to external devices 1610 // (TVs, projectors etc.) 1611 // True if casting is currently allowed 1612 bool mAllowCasting = false; 1613 // True if currently casting this video 1614 bool mIsCasting = false; 1615 1616 // Set while there are some OutputMediaStreams this media element's enabled 1617 // and selected tracks are captured into. When set, all tracks are captured 1618 // into the graph of this dummy track. 1619 // NB: This is a SharedDummyTrack to allow non-default graphs (AudioContexts 1620 // with an explicit sampleRate defined) to capture this element. When 1621 // cross-graph tracks are supported, this can become a bool. 1622 Watchable<RefPtr<SharedDummyTrack>> mTracksCaptured; 1623 1624 // True if the sound is being captured. 1625 bool mAudioCaptured = false; 1626 1627 // If TRUE then the media element was actively playing before the currently 1628 // in progress seeking. If FALSE then the media element is either not seeking 1629 // or was not actively playing before the current seek. Used to decide whether 1630 // to raise the 'waiting' event as per 4.7.1.8 in HTML 5 specification. 1631 bool mPlayingBeforeSeek = false; 1632 1633 // True if this element is suspended because the document is inactive or the 1634 // inactive docshell is not allowing media to play. 1635 bool mSuspendedByInactiveDocOrDocshell = false; 1636 1637 // True if event delivery is suspended (mSuspendedByInactiveDocOrDocshell 1638 // must also be true). 1639 bool mEventDeliveryPaused = false; 1640 1641 // True if we're running the "load()" method. 1642 bool mIsRunningLoadMethod = false; 1643 1644 // True if we're running or waiting to run queued tasks due to an explicit 1645 // call to "load()". 1646 bool mIsDoingExplicitLoad = false; 1647 1648 // True if we're loading the resource from the child source elements. 1649 bool mIsLoadingFromSourceChildren = false; 1650 1651 // True if we're delaying the "load" event. They are delayed until either 1652 // an error occurs, or the first frame is loaded. 1653 bool mDelayingLoadEvent = false; 1654 1655 // True when we've got a task queued to call SelectResource(), 1656 // or while we're running SelectResource(). 1657 bool mIsRunningSelectResource = false; 1658 1659 // True when we already have select resource call queued 1660 bool mHaveQueuedSelectResource = false; 1661 1662 // True if we suspended the decoder because we were paused, 1663 // preloading metadata is enabled, autoplay was not enabled, and we loaded 1664 // the first frame. 1665 bool mSuspendedAfterFirstFrame = false; 1666 1667 // True if we are allowed to suspend the decoder because we were paused, 1668 // preloading metdata was enabled, autoplay was not enabled, and we loaded 1669 // the first frame. 1670 bool mAllowSuspendAfterFirstFrame = true; 1671 1672 // True if we've played or completed a seek. We use this to determine 1673 // when the poster frame should be shown. 1674 bool mHasPlayedOrSeeked = false; 1675 1676 // True if we've added a reference to ourselves to keep the element 1677 // alive while no-one is referencing it but the element may still fire 1678 // events of its own accord. 1679 bool mHasSelfReference = false; 1680 1681 // True if we've received a notification that the engine is shutting 1682 // down. 1683 bool mShuttingDown = false; 1684 1685 // True if we've suspended a load in the resource selection algorithm 1686 // due to loading a preload:none media. When true, the resource we'll 1687 // load when the user initiates either playback or an explicit load is 1688 // stored in mPreloadURI. 1689 bool mSuspendedForPreloadNone = false; 1690 1691 // True if we've connected mSrcStream to the media element output. 1692 bool mSrcStreamIsPlaying = false; 1693 1694 // True if we should set nsIClassOfService::UrgentStart to the channel to 1695 // get the response ASAP for better user responsiveness. 1696 bool mUseUrgentStartForChannel = false; 1697 1698 // The CORS mode when loading the media element 1699 CORSMode mCORSMode = CORS_NONE; 1700 1701 // Info about the played media. 1702 MediaInfo mMediaInfo; 1703 1704 // True if the media has encryption information. 1705 bool mIsEncrypted = false; 1706 1707 enum WaitingForKeyState { 1708 NOT_WAITING_FOR_KEY = 0, 1709 WAITING_FOR_KEY = 1, 1710 WAITING_FOR_KEY_DISPATCHED = 2 1711 }; 1712 1713 // True when the CDM cannot decrypt the current block due to lacking a key. 1714 // Note: the "waitingforkey" event is not dispatched until all decoded data 1715 // has been rendered. 1716 WaitingForKeyState mWaitingForKey = NOT_WAITING_FOR_KEY; 1717 1718 // Listens for waitingForKey events from the owned decoder. 1719 MediaEventListener mWaitingForKeyListener; 1720 1721 // Init Data that needs to be sent in 'encrypted' events in MetadataLoaded(). 1722 EncryptionInfo mPendingEncryptedInitData; 1723 1724 // True if the media's channel's download has been suspended. 1725 Watchable<bool> mDownloadSuspendedByCache = { 1726 false, "HTMLMediaElement::mDownloadSuspendedByCache"}; 1727 1728 // Disable the video playback by track selection. This flag might not be 1729 // enough if we ever expand the ability of supporting multi-tracks video 1730 // playback. 1731 bool mDisableVideo = false; 1732 1733 RefPtr<TextTrackManager> mTextTrackManager; 1734 1735 RefPtr<AudioTrackList> mAudioTrackList; 1736 1737 RefPtr<VideoTrackList> mVideoTrackList; 1738 1739 UniquePtr<MediaStreamTrackListener> mMediaStreamTrackListener; 1740 1741 // The principal guarding mVideoFrameContainer access when playing a 1742 // MediaStream. 1743 nsCOMPtr<nsIPrincipal> mSrcStreamVideoPrincipal; 1744 1745 // True if the autoplay media was blocked because it hadn't loaded metadata 1746 // yet. 1747 bool mBlockedAsWithoutMetadata = false; 1748 1749 // This promise is used to notify MediaElementAudioSourceNode that media 1750 // element is allowed to play when MediaElement is used as a source for web 1751 // audio. 1752 MozPromiseHolder<GenericNonExclusivePromise> mAllowedToPlayPromise; 1753 1754 // True if media has ever been blocked for autoplay, it's used to notify front 1755 // end to show the correct blocking icon when the document goes back from 1756 // bfcache. 1757 bool mHasEverBeenBlockedForAutoplay = false; 1758 1759 // True if we have dispatched a task for text track changed, will be unset 1760 // when we starts processing text track changed. 1761 // https://html.spec.whatwg.org/multipage/media.html#pending-text-track-change-notification-flag 1762 bool mPendingTextTrackChanged = false; 1763 1764 public: 1765 // This function will be called whenever a text track that is in a media 1766 // element's list of text tracks has its text track mode change value 1767 void NotifyTextTrackModeChanged(); 1768 1769 public: 1770 // Helper class to measure times for playback telemetry stats 1771 class TimeDurationAccumulator { 1772 public: TimeDurationAccumulator()1773 TimeDurationAccumulator() : mCount(0) {} Start()1774 void Start() { 1775 if (IsStarted()) { 1776 return; 1777 } 1778 mStartTime = TimeStamp::Now(); 1779 } Pause()1780 void Pause() { 1781 if (!IsStarted()) { 1782 return; 1783 } 1784 mSum += (TimeStamp::Now() - mStartTime); 1785 mCount++; 1786 mStartTime = TimeStamp(); 1787 } IsStarted()1788 bool IsStarted() const { return !mStartTime.IsNull(); } Total()1789 double Total() const { 1790 if (!IsStarted()) { 1791 return mSum.ToSeconds(); 1792 } 1793 // Add current running time until now, but keep it running. 1794 return (mSum + (TimeStamp::Now() - mStartTime)).ToSeconds(); 1795 } Count()1796 uint32_t Count() const { 1797 if (!IsStarted()) { 1798 return mCount; 1799 } 1800 // Count current run in this report, without increasing the stored count. 1801 return mCount + 1; 1802 } Reset()1803 void Reset() { 1804 mStartTime = TimeStamp(); 1805 mSum = TimeDuration(); 1806 mCount = 0; 1807 } 1808 1809 private: 1810 TimeStamp mStartTime; 1811 TimeDuration mSum; 1812 uint32_t mCount; 1813 }; 1814 1815 private: 1816 already_AddRefed<PlayPromise> CreatePlayPromise(ErrorResult& aRv) const; 1817 1818 void UpdateHadAudibleAutoplayState(); 1819 MaybeBeginCloningVisually()1820 virtual void MaybeBeginCloningVisually(){}; 1821 1822 uint32_t GetPreloadDefault() const; 1823 uint32_t GetPreloadDefaultAuto() const; 1824 1825 /** 1826 * This function is called by AfterSetAttr and OnAttrSetButNotChanged. 1827 * It will not be called if the value is being unset. 1828 * 1829 * @param aNamespaceID the namespace of the attr being set 1830 * @param aName the localname of the attribute being set 1831 * @param aNotify Whether we plan to notify document observers. 1832 */ 1833 void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName, bool aNotify); 1834 1835 // Total time a video has spent playing. 1836 TimeDurationAccumulator mPlayTime; 1837 1838 // Total time a video has spent playing while hidden. 1839 TimeDurationAccumulator mHiddenPlayTime; 1840 1841 // Total time a video has (or would have) spent in video-decode-suspend mode. 1842 TimeDurationAccumulator mVideoDecodeSuspendTime; 1843 1844 // Total time a video has spent playing on the current load, it would be reset 1845 // when media aborts the current load; be paused when the docuemt enters the 1846 // bf-cache and be resumed when the docuemt leaves the bf-cache. 1847 TimeDurationAccumulator mCurrentLoadPlayTime; 1848 1849 // True if media has ever been blocked by autoplay policy before. 1850 bool mHasPlayEverBeenBlocked = false; 1851 1852 // Report the Telemetry about whether media played over the specific time 1853 // threshold. 1854 void ReportPlayedTimeAfterBlockedTelemetry(); 1855 1856 // True if Init() has been called after construction 1857 bool mInitialized = false; 1858 1859 // True if user has called load(), seek() or element has started playing 1860 // before. It's *only* use for `click-to-play` blocking autoplay policy. 1861 // In addition, we would reset this once media aborts current load. 1862 bool mIsBlessed = false; 1863 1864 // True if the first frame has been successfully loaded. 1865 Watchable<bool> mFirstFrameLoaded = {false, 1866 "HTMLMediaElement::mFirstFrameLoaded"}; 1867 1868 // Media elements also have a default playback start position, which must 1869 // initially be set to zero seconds. This time is used to allow the element to 1870 // be seeked even before the media is loaded. 1871 double mDefaultPlaybackStartPosition = 0.0; 1872 1873 // True if media element has been marked as 'tainted' and can't 1874 // participate in video decoder suspending. 1875 bool mHasSuspendTaint = false; 1876 1877 // True if media element has been forced into being considered 'hidden'. 1878 // For use by mochitests. Enabling pref "media.test.video-suspend" 1879 bool mForcedHidden = false; 1880 1881 Visibility mVisibilityState = Visibility::Untracked; 1882 1883 UniquePtr<ErrorSink> mErrorSink; 1884 1885 // This wrapper will handle all audio channel related stuffs, eg. the 1886 // operations of tab audio indicator, Fennec's media control. Note: 1887 // mAudioChannelWrapper might be null after GC happened. 1888 RefPtr<AudioChannelAgentCallback> mAudioChannelWrapper; 1889 1890 // A list of pending play promises. The elements are pushed during the play() 1891 // method call and are resolved/rejected during further playback steps. 1892 nsTArray<RefPtr<PlayPromise>> mPendingPlayPromises; 1893 1894 // A list of already-dispatched but not yet run 1895 // nsResolveOrRejectPendingPlayPromisesRunners. 1896 // Runners whose Run() method is called remove themselves from this list. 1897 // We keep track of these because the load algorithm resolves/rejects all 1898 // already-dispatched pending play promises. 1899 nsTArray<nsResolveOrRejectPendingPlayPromisesRunner*> 1900 mPendingPlayPromisesRunners; 1901 1902 // A pending seek promise which is created at Seek() method call and is 1903 // resolved/rejected at AsyncResolveSeekDOMPromiseIfExists()/ 1904 // AsyncRejectSeekDOMPromiseIfExists() methods. 1905 RefPtr<dom::Promise> mSeekDOMPromise; 1906 1907 // Return true if the docshell is inactive and explicitly wants to stop media 1908 // playing in that shell. 1909 bool ShouldBeSuspendedByInactiveDocShell() const; 1910 1911 // For debugging bug 1407148. 1912 void AssertReadyStateIsNothing(); 1913 1914 // Contains the unique id of the sink device and the device info. 1915 // The initial value is ("", nullptr) and the default output device is used. 1916 // It can contain an invalid id and info if the device has been 1917 // unplugged. It can be set to ("", nullptr). It follows the spec attribute: 1918 // https://w3c.github.io/mediacapture-output/#htmlmediaelement-extensions 1919 // Read/Write from the main thread only. 1920 std::pair<nsString, RefPtr<AudioDeviceInfo>> mSink; 1921 1922 // This flag is used to control when the user agent is to show a poster frame 1923 // for a video element instead of showing the video contents. 1924 // https://html.spec.whatwg.org/multipage/media.html#show-poster-flag 1925 bool mShowPoster; 1926 1927 // We may delay starting playback of a media for an unvisited tab until it's 1928 // going to foreground. We would create ResumeDelayedMediaPlaybackAgent to 1929 // handle related operations at the time whenever delaying media playback is 1930 // needed. 1931 void CreateResumeDelayedMediaPlaybackAgentIfNeeded(); 1932 void ClearResumeDelayedMediaPlaybackAgentIfNeeded(); 1933 RefPtr<ResumeDelayedPlaybackAgent> mResumeDelayedPlaybackAgent; 1934 MozPromiseRequestHolder<ResumeDelayedPlaybackAgent::ResumePromise> 1935 mResumePlaybackRequest; 1936 1937 // We use MediaControlEventListener to listen media control keys event, which 1938 // would play or pause media element according to different events. 1939 void StartListeningMediaControlEventIfNeeded(); 1940 void StopListeningMediaControlEventIfNeeded(); 1941 RefPtr<MediaControlEventListener> mMediaControlEventListener; 1942 1943 // Return true if the media element is being used in picture in picture mode. 1944 bool IsBeingUsedInPictureInPictureMode() const; 1945 }; 1946 1947 // Check if the context is chrome or has the debugger or tabs permission 1948 bool HasDebuggerOrTabsPrivilege(JSContext* aCx, JSObject* aObj); 1949 1950 } // namespace dom 1951 } // namespace mozilla 1952 1953 #endif // mozilla_dom_HTMLMediaElement_h 1954