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