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