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