tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MediaPlaybackStatus.h (6123B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #ifndef DOM_MEDIA_MEDIACONTROL_MEDIAPLAYBACKSTATUS_H_
      6 #define DOM_MEDIA_MEDIACONTROL_MEDIAPLAYBACKSTATUS_H_
      7 
      8 #include "mozilla/DefineEnum.h"
      9 #include "mozilla/Maybe.h"
     10 #include "mozilla/dom/MediaSession.h"
     11 #include "nsID.h"
     12 #include "nsISupportsImpl.h"
     13 #include "nsTArray.h"
     14 #include "nsTHashMap.h"
     15 
     16 namespace mozilla::dom {
     17 
     18 /**
     19 * This enum is used to update controlled media state to the media controller in
     20 * the chrome process.
     21 * `eStarted`: media has successfully registered to the content media controller
     22 * `ePlayed` : media has started playing
     23 * `ePaused` : media has paused playing, but still can be resumed by content
     24 *             media controller
     25 * `eStopped`: media has unregistered from the content media controller, we can
     26 *             not control it anymore
     27 */
     28 MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING(MediaPlaybackState, uint32_t,
     29                                             (eStarted, ePlayed, ePaused,
     30                                              eStopped));
     31 
     32 /**
     33 * This enum is used to update controlled media audible audible state to the
     34 * media controller in the chrome process.
     35 */
     36 MOZ_DEFINE_ENUM_CLASS_WITH_BASE_AND_TOSTRING(MediaAudibleState, bool,
     37                                             (eInaudible, eAudible));
     38 
     39 /**
     40 * MediaPlaybackStatus is an internal module for the media controller, it
     41 * represents a tab's media related status, such like "does the tab contain any
     42 * controlled media? is the tab playing? is the tab audible?".
     43 *
     44 * The reason we need this class is that we would like to encapsulate the
     45 * details of determining the tab's media status. A tab can contains multiple
     46 * browsing contexts, and each browsing context can have different media status.
     47 * The final media status would be decided by checking all those context status.
     48 *
     49 * Use `UpdateMediaXXXState()` to update controlled media status, and use
     50 * `IsXXX()` methods to acquire the playback status of the tab.
     51 *
     52 * As we know each context's audible state, we can decide which context should
     53 * owns the audio focus when multiple contexts are all playing audible media at
     54 * the same time. In that cases, the latest context that plays media would own
     55 * the audio focus. When the context owning the audio focus is destroyed, we
     56 * would see if there is another other context still playing audible media, and
     57 * switch the audio focus to another context.
     58 */
     59 class MediaPlaybackStatus final {
     60 public:
     61  void UpdateMediaPlaybackState(uint64_t aContextId, MediaPlaybackState aState);
     62  void UpdateMediaAudibleState(uint64_t aContextId, MediaAudibleState aState);
     63  void UpdateGuessedPositionState(uint64_t aContextId, const nsID& aElementId,
     64                                  const Maybe<PositionState>& aState);
     65 
     66  bool IsPlaying() const;
     67  bool IsAudible() const;
     68  bool IsAnyMediaBeingControlled() const;
     69  Maybe<PositionState> GuessedMediaPositionState(
     70      Maybe<uint64_t> aPreferredContextId) const;
     71 
     72  Maybe<uint64_t> GetAudioFocusOwnerContextId() const;
     73 
     74 private:
     75  /**
     76   * This internal class stores detailed media status of controlled media for
     77   * a browsing context.
     78   */
     79  class ContextMediaInfo final {
     80   public:
     81    explicit ContextMediaInfo(uint64_t aContextId) : mContextId(aContextId) {}
     82    ~ContextMediaInfo() = default;
     83 
     84    void IncreaseControlledMediaNum() {
     85 #ifndef FUZZING_SNAPSHOT
     86      MOZ_DIAGNOSTIC_ASSERT(mControlledMediaNum < UINT_MAX);
     87 #endif
     88      mControlledMediaNum++;
     89    }
     90    void DecreaseControlledMediaNum() {
     91 #ifndef FUZZING_SNAPSHOT
     92      MOZ_DIAGNOSTIC_ASSERT(mControlledMediaNum > 0);
     93 #endif
     94      mControlledMediaNum--;
     95    }
     96    void IncreasePlayingMediaNum() {
     97 #ifndef FUZZING_SNAPSHOT
     98      MOZ_DIAGNOSTIC_ASSERT(mPlayingMediaNum < mControlledMediaNum);
     99 #endif
    100      mPlayingMediaNum++;
    101    }
    102    void DecreasePlayingMediaNum() {
    103 #ifndef FUZZING_SNAPSHOT
    104      MOZ_DIAGNOSTIC_ASSERT(mPlayingMediaNum > 0);
    105 #endif
    106      mPlayingMediaNum--;
    107    }
    108    void IncreaseAudibleMediaNum() {
    109 #ifndef FUZZING_SNAPSHOT
    110      MOZ_DIAGNOSTIC_ASSERT(mAudibleMediaNum < mPlayingMediaNum);
    111 #endif
    112      mAudibleMediaNum++;
    113    }
    114    void DecreaseAudibleMediaNum() {
    115 #ifndef FUZZING_SNAPSHOT
    116      MOZ_DIAGNOSTIC_ASSERT(mAudibleMediaNum > 0);
    117 #endif
    118      mAudibleMediaNum--;
    119    }
    120    bool IsPlaying() const { return mPlayingMediaNum > 0; }
    121    bool IsAudible() const { return mAudibleMediaNum > 0; }
    122    bool IsAnyMediaBeingControlled() const { return mControlledMediaNum > 0; }
    123    uint64_t Id() const { return mContextId; }
    124 
    125    Maybe<PositionState> GuessedPositionState() const;
    126    void UpdateGuessedPositionState(const nsID& aElementId,
    127                                    const Maybe<PositionState>& aState);
    128 
    129   private:
    130    /**
    131     * The possible value for those three numbers should follow this rule,
    132     * mControlledMediaNum >= mPlayingMediaNum >= mAudibleMediaNum
    133     */
    134    uint32_t mControlledMediaNum = 0;
    135    uint32_t mAudibleMediaNum = 0;
    136    uint32_t mPlayingMediaNum = 0;
    137    uint64_t mContextId = 0;
    138 
    139    /**
    140     * Contains the guessed position state of all media elements in this
    141     * browsing context identified by their ID.
    142     */
    143    nsTHashMap<nsID, PositionState> mGuessedPositionStateMap;
    144  };
    145 
    146  ContextMediaInfo& GetNotNullContextInfo(uint64_t aContextId);
    147  void DestroyContextInfo(uint64_t aContextId);
    148 
    149  void ChooseNewContextToOwnAudioFocus();
    150  void SetOwningAudioFocusContextId(Maybe<uint64_t>&& aContextId);
    151  bool IsContextOwningAudioFocus(uint64_t aContextId) const;
    152  bool ShouldRequestAudioFocusForInfo(const ContextMediaInfo& aInfo) const;
    153  bool ShouldAbandonAudioFocusForInfo(const ContextMediaInfo& aInfo) const;
    154 
    155  // This contains all the media status of browsing contexts within a tab.
    156  nsTHashMap<uint64_t, UniquePtr<ContextMediaInfo>> mContextInfoMap;
    157  Maybe<uint64_t> mOwningAudioFocusContextId;
    158 };
    159 
    160 }  // namespace mozilla::dom
    161 
    162 #endif  //  DOM_MEDIA_MEDIACONTROL_MEDIAPLAYBACKSTATUS_H_