163 lines
6 KiB
C++
163 lines
6 KiB
C++
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef DOM_MEDIA_MEDIACONTROL_MEDIAPLAYBACKSTATUS_H_
|
|
#define DOM_MEDIA_MEDIACONTROL_MEDIAPLAYBACKSTATUS_H_
|
|
|
|
#include "mozilla/DefineEnum.h"
|
|
#include "mozilla/Maybe.h"
|
|
#include "mozilla/RefPtr.h"
|
|
#include "mozilla/dom/MediaSession.h"
|
|
#include "nsID.h"
|
|
#include "nsISupportsImpl.h"
|
|
#include "nsTArray.h"
|
|
#include "nsTHashMap.h"
|
|
|
|
namespace mozilla::dom {
|
|
|
|
/**
|
|
* This enum is used to update controlled media state to the media controller in
|
|
* the chrome process.
|
|
* `eStarted`: media has successfully registered to the content media controller
|
|
* `ePlayed` : media has started playing
|
|
* `ePaused` : media has paused playing, but still can be resumed by content
|
|
* media controller
|
|
* `eStopped`: media has unregistered from the content media controller, we can
|
|
* not control it anymore
|
|
*/
|
|
MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING(MediaPlaybackState, uint32_t,
|
|
(eStarted, ePlayed, ePaused,
|
|
eStopped));
|
|
|
|
/**
|
|
* This enum is used to update controlled media audible audible state to the
|
|
* media controller in the chrome process.
|
|
*/
|
|
MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING(MediaAudibleState, bool,
|
|
(eInaudible, eAudible));
|
|
|
|
/**
|
|
* MediaPlaybackStatus is an internal module for the media controller, it
|
|
* represents a tab's media related status, such like "does the tab contain any
|
|
* controlled media? is the tab playing? is the tab audible?".
|
|
*
|
|
* The reason we need this class is that we would like to encapsulate the
|
|
* details of determining the tab's media status. A tab can contains multiple
|
|
* browsing contexts, and each browsing context can have different media status.
|
|
* The final media status would be decided by checking all those context status.
|
|
*
|
|
* Use `UpdateMediaXXXState()` to update controlled media status, and use
|
|
* `IsXXX()` methods to acquire the playback status of the tab.
|
|
*
|
|
* As we know each context's audible state, we can decide which context should
|
|
* owns the audio focus when multiple contexts are all playing audible media at
|
|
* the same time. In that cases, the latest context that plays media would own
|
|
* the audio focus. When the context owning the audio focus is destroyed, we
|
|
* would see if there is another other context still playing audible media, and
|
|
* switch the audio focus to another context.
|
|
*/
|
|
class MediaPlaybackStatus final {
|
|
public:
|
|
void UpdateMediaPlaybackState(uint64_t aContextId, MediaPlaybackState aState);
|
|
void UpdateMediaAudibleState(uint64_t aContextId, MediaAudibleState aState);
|
|
void UpdateGuessedPositionState(uint64_t aContextId, const nsID& aElementId,
|
|
const Maybe<PositionState>& aState);
|
|
|
|
bool IsPlaying() const;
|
|
bool IsAudible() const;
|
|
bool IsAnyMediaBeingControlled() const;
|
|
Maybe<PositionState> GuessedMediaPositionState(
|
|
Maybe<uint64_t> aPreferredContextId) const;
|
|
|
|
Maybe<uint64_t> GetAudioFocusOwnerContextId() const;
|
|
|
|
private:
|
|
/**
|
|
* This internal class stores detailed media status of controlled media for
|
|
* a browsing context.
|
|
*/
|
|
class ContextMediaInfo final {
|
|
public:
|
|
explicit ContextMediaInfo(uint64_t aContextId) : mContextId(aContextId) {}
|
|
~ContextMediaInfo() = default;
|
|
|
|
void IncreaseControlledMediaNum() {
|
|
#ifndef FUZZING_SNAPSHOT
|
|
MOZ_DIAGNOSTIC_ASSERT(mControlledMediaNum < UINT_MAX);
|
|
#endif
|
|
mControlledMediaNum++;
|
|
}
|
|
void DecreaseControlledMediaNum() {
|
|
#ifndef FUZZING_SNAPSHOT
|
|
MOZ_DIAGNOSTIC_ASSERT(mControlledMediaNum > 0);
|
|
#endif
|
|
mControlledMediaNum--;
|
|
}
|
|
void IncreasePlayingMediaNum() {
|
|
#ifndef FUZZING_SNAPSHOT
|
|
MOZ_DIAGNOSTIC_ASSERT(mPlayingMediaNum < mControlledMediaNum);
|
|
#endif
|
|
mPlayingMediaNum++;
|
|
}
|
|
void DecreasePlayingMediaNum() {
|
|
#ifndef FUZZING_SNAPSHOT
|
|
MOZ_DIAGNOSTIC_ASSERT(mPlayingMediaNum > 0);
|
|
#endif
|
|
mPlayingMediaNum--;
|
|
}
|
|
void IncreaseAudibleMediaNum() {
|
|
#ifndef FUZZING_SNAPSHOT
|
|
MOZ_DIAGNOSTIC_ASSERT(mAudibleMediaNum < mPlayingMediaNum);
|
|
#endif
|
|
mAudibleMediaNum++;
|
|
}
|
|
void DecreaseAudibleMediaNum() {
|
|
#ifndef FUZZING_SNAPSHOT
|
|
MOZ_DIAGNOSTIC_ASSERT(mAudibleMediaNum > 0);
|
|
#endif
|
|
mAudibleMediaNum--;
|
|
}
|
|
bool IsPlaying() const { return mPlayingMediaNum > 0; }
|
|
bool IsAudible() const { return mAudibleMediaNum > 0; }
|
|
bool IsAnyMediaBeingControlled() const { return mControlledMediaNum > 0; }
|
|
uint64_t Id() const { return mContextId; }
|
|
|
|
Maybe<PositionState> GuessedPositionState() const;
|
|
void UpdateGuessedPositionState(const nsID& aElementId,
|
|
const Maybe<PositionState>& aState);
|
|
|
|
private:
|
|
/**
|
|
* The possible value for those three numbers should follow this rule,
|
|
* mControlledMediaNum >= mPlayingMediaNum >= mAudibleMediaNum
|
|
*/
|
|
uint32_t mControlledMediaNum = 0;
|
|
uint32_t mAudibleMediaNum = 0;
|
|
uint32_t mPlayingMediaNum = 0;
|
|
uint64_t mContextId = 0;
|
|
|
|
/**
|
|
* Contains the guessed position state of all media elements in this
|
|
* browsing context identified by their ID.
|
|
*/
|
|
nsTHashMap<nsID, PositionState> mGuessedPositionStateMap;
|
|
};
|
|
|
|
ContextMediaInfo& GetNotNullContextInfo(uint64_t aContextId);
|
|
void DestroyContextInfo(uint64_t aContextId);
|
|
|
|
void ChooseNewContextToOwnAudioFocus();
|
|
void SetOwningAudioFocusContextId(Maybe<uint64_t>&& aContextId);
|
|
bool IsContextOwningAudioFocus(uint64_t aContextId) const;
|
|
bool ShouldRequestAudioFocusForInfo(const ContextMediaInfo& aInfo) const;
|
|
bool ShouldAbandonAudioFocusForInfo(const ContextMediaInfo& aInfo) const;
|
|
|
|
// This contains all the media status of browsing contexts within a tab.
|
|
nsTHashMap<uint64_t, UniquePtr<ContextMediaInfo>> mContextInfoMap;
|
|
Maybe<uint64_t> mOwningAudioFocusContextId;
|
|
};
|
|
|
|
} // namespace mozilla::dom
|
|
|
|
#endif // DOM_MEDIA_MEDIACONTROL_MEDIAPLAYBACKSTATUS_H_
|