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