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