DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (c68fe15a81fc)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
/* This Source Code Form is subject to the terms of the Mozilla Public
/* 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_MEDIASTATUSMANAGER_H_
#define DOM_MEDIA_MEDIACONTROL_MEDIASTATUSMANAGER_H_
#define DOM_MEDIA_MEDIACONTROL_MEDIASTATUSMANAGER_H_

#include "MediaControlKeySource.h"
#include "MediaEventSource.h"
#include "MediaPlaybackStatus.h"
#include "mozilla/dom/MediaMetadata.h"
#include "nsDataHashtable.h"
#include "mozilla/dom/MediaSessionBinding.h"
#include "mozilla/Maybe.h"
#include "nsDataHashtable.h"
#include "nsISupportsImpl.h"


namespace mozilla {
namespace dom {

class MediaSessionInfo {
 public:
  MediaSessionInfo() = default;
    mMetadata.emplace(aMetadata);

  explicit MediaSessionInfo(MediaMetadataBase& aMetadata) {
    mMetadata.emplace(aMetadata);
  }

    mMetadata.emplace(aMetadata);
  MediaSessionInfo(MediaMetadataBase& aMetadata,
                   MediaSessionPlaybackState& aState) {
    mMetadata.emplace(aMetadata);
  static MediaSessionInfo EmptyInfo() { return MediaSessionInfo(); }
    mDeclaredPlaybackState = aState;
  }

  static MediaSessionInfo EmptyInfo() { return MediaSessionInfo(); }

  MediaSessionPlaybackState mDeclaredPlaybackState =
  static uint32_t GetActionBitMask(MediaSessionAction aAction) {
    return 1 << static_cast<uint8_t>(aAction);
  }

  void EnableAction(MediaSessionAction aAction) {
 * IMediaInfoUpdater is an interface which provides methods to update the media
    mSupportedActions |= GetActionBitMask(aAction);
  }

  void DisableAction(MediaSessionAction aAction) {
    mSupportedActions &= ~GetActionBitMask(aAction);

  }

  bool IsActionSupported(MediaSessionAction aAction) const {
    return mSupportedActions & GetActionBitMask(aAction);
  }


  // These attributes are all propagated from the media session in the content
  // process.
  Maybe<MediaMetadataBase> mMetadata;
  MediaSessionPlaybackState mDeclaredPlaybackState =
      MediaSessionPlaybackState::None;

  // Use bitwise to store the supported actions.
  uint32_t mSupportedActions = 0;
};

/**

 * IMediaInfoUpdater is an interface which provides methods to update the media
 * related information that happens in the content process.
 */
class IMediaInfoUpdater {
  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING

  virtual void UpdateMetadata(uint64_t aBrowsingContextId,
  // Use this method to update controlled media's playback state and the
  // browsing context where controlled media exists. When notifying the state
                              const Maybe<MediaMetadataBase>& aMetadata) = 0;
  // change, we MUST follow the following rules.
  // (1) `eStart` MUST be the first state and `eStop` MUST be the last state
  // (2) Do not notify same state again
  // (3) `ePaused` can only be notified after notifying `ePlayed`.
  virtual void NotifyMediaPlaybackChanged(uint64_t aBrowsingContextId,
};
                                          MediaPlaybackState aState) = 0;

  // Use this method to update the audible state of controlled media, and MUST
  // follow the following rules in which `audible` and `inaudible` should be a
  // pair. `inaudible` should always be notified after `audible`. When audible
 * the active media session ID if it exists.
  // media paused, `inaudible` should be notified
  // Eg. (O) `audible` -> `inaudible` -> `audible` -> `inaudible`
  //     (X) `inaudible` -> `audible`    [notify `inaudible` before `audible`]
  //     (X) `audible` -> `audible`      [notify `audible` twice]
  //     (X) `audible` -> (media pauses) [forgot to notify `inaudible`]
 *
  virtual void NotifyMediaAudibleChanged(uint64_t aBrowsingContextId,
                                         MediaAudibleState aState) = 0;

  // Use this method to update media session's declared playback state for the
  // specific media session.
 * control interface. In addition, we can use it to get the current media
  virtual void SetDeclaredPlaybackState(uint64_t aBrowsingContextId,
                                        MediaSessionPlaybackState aState) = 0;

  // Use these methods to update controller's media session list. We'd use it
  // when media session is created/destroyed in the content process.
 * controller which is determined by MediaControlService.
  virtual void NotifySessionCreated(uint64_t aBrowsingContextId) = 0;
  virtual void NotifySessionDestroyed(uint64_t aBrowsingContextId) = 0;

  // Use this method to update the metadata for the specific media session.
  virtual void UpdateMetadata(uint64_t aBrowsingContextId,
                              const Maybe<MediaMetadataBase>& aMetadata) = 0;

  // Use this method to update the picture in picture mode state of controlled
  // media, and it's safe to notify same state again.
  void NotifyMediaPlaybackChanged(uint64_t aBrowsingContextId,
  virtual void SetIsInPictureInPictureMode(uint64_t aBrowsingContextId,
                                           bool aIsInPictureInPictureMode) = 0;

  // Use these methods to update the supported media session action for the
  // specific media session. For a media session from a given browsing context,
                                MediaSessionPlaybackState aState) override;
  // do not re-enable the same action, or disable the action without enabling it
  // before.
  virtual void EnableAction(uint64_t aBrowsingContextId,
                            MediaSessionAction aAction) = 0;

  virtual void DisableAction(uint64_t aBrowsingContextId,
  // Return active media session's metadata if active media session exists and
                             MediaSessionAction aAction) = 0;
};

/**
 * MediaStatusManager would decide the media related status which can represents
  bool IsMediaAudible() const;
 * the whole tab. The status includes the playback status, tab's metadata and
 * the active media session ID if it exists.
 *
 * We would use `IMediaInfoUpdater` methods to update the media playback related
 * information and then use `MediaPlaybackStatus` to determine the final
    return mMetadataChangedEvent;
 * playback state.
 *
 * The metadata would be the one from the active media session, or the default
 * one. This class would determine which media session is an active media
 * session [1] whithin a tab. It tracks all alive media sessions within a tab

 * and store their metadata which could be used to show on the virtual media
 * control interface. In addition, we can use it to get the current media
 * metadata even if there is no media session existing. However, the meaning of
 * active media session here is not equal to the definition from the spec [1].
 * We just choose the session which is the active one inside the tab, the global
  uint64_t mTopLevelBrowsingContextId;
 * active media session among different tabs would be the one inside the main
 * controller which is determined by MediaControlService.
 *
 * [1] https://w3c.github.io/mediasession/#active-media-session
  Maybe<uint64_t> mActiveMediaSessionContextId;
 */
class MediaStatusManager : public IMediaInfoUpdater {
 public:
  explicit MediaStatusManager(uint64_t aBrowsingContextId);

  MediaMetadataBase CreateDefaultMetadata() const;
  // IMediaInfoUpdater's methods
  void NotifyMediaPlaybackChanged(uint64_t aBrowsingContextId,
                                  MediaPlaybackState aState) override;
  void NotifyMediaAudibleChanged(uint64_t aBrowsingContextId,
                                 MediaAudibleState aState) override;
  void SetDeclaredPlaybackState(uint64_t aSessionContextId,
                                MediaSessionPlaybackState aState) override;
  void NotifySessionCreated(uint64_t aSessionContextId) override;
  void HandleAudioFocusOwnerChanged(Maybe<uint64_t>& aBrowsingContextId);
  void NotifySessionDestroyed(uint64_t aSessionContextId) override;
  void UpdateMetadata(uint64_t aSessionContextId,
                      const Maybe<MediaMetadataBase>& aMetadata) override;
  void EnableAction(uint64_t aBrowsingContextId,
                    MediaSessionAction aAction) override;

  void DisableAction(uint64_t aBrowsingContextId,
                     MediaSessionAction aAction) override;

  // Return active media session's metadata if active media session exists and
  // it has already set its metadata. Otherwise, return default media metadata

  // which is based on website's title and favicon.
  MediaMetadataBase GetCurrentMediaMetadata() const;

  bool IsMediaAudible() const;
  // This state can match to the `guessed playback state` in the spec [1], it
  bool IsMediaPlaying() const;
  bool IsAnyMediaBeingControlled() const;

  // This event would be notified when the active media session's metadata
  // changes.
  // media.
  MediaEventSource<MediaMetadataBase>& MetadataChangedEvent() {
    return mMetadataChangedEvent;
  }

  // Return the actual playback state.
  // This playback state would be the final playback which can be used to know
  MediaSessionPlaybackState GetState() const;

 protected:
  ~MediaStatusManager() = default;
  virtual void HandleActualPlaybackStateChanged() = 0;


  // This event would be notified when the active media session changes its
  // supported actions.
  MediaEventSource<nsTArray<MediaSessionAction>>&
  MediaPlaybackStatus mPlaybackStatusDelegate;
  SupportedActionsChangedEvent() {
};
    return mSupportedActionsChangedEvent;
  }
}  // namespace mozilla

  uint64_t mTopLevelBrowsingContextId;

  // Within a tab, the Id of the browsing context which has already created a
  // media session and owns the audio focus within a tab.
  Maybe<uint64_t> mActiveMediaSessionContextId;

 private:
  nsString GetDefaultFaviconURL() const;
  nsString GetDefaultTitle() const;
  MediaMetadataBase CreateDefaultMetadata() const;
  bool IsInPrivateBrowsing() const;
  void FillMissingTitleAndArtworkIfNeeded(MediaMetadataBase& aMetadata) const;

  bool IsSessionOwningAudioFocus(uint64_t aBrowsingContextId) const;
  void SetActiveMediaSessionContextId(uint64_t aBrowsingContextId);
  void ClearActiveMediaSessionContextIdIfNeeded();
  void HandleAudioFocusOwnerChanged(Maybe<uint64_t>& aBrowsingContextId);

  void NotifySupportedKeysChangedIfNeeded(uint64_t aBrowsingContextId);

  // Return a copyable array filled with the supported media session actions.
  // Use copyable array so that we can use the result as a parameter for the
  // media event.
  CopyableTArray<MediaSessionAction> GetSupportedActions() const;

  // When the amount of playing media changes, we would use this function to
  // update the guessed playback state.
  void SetGuessedPlayState(MediaSessionPlaybackState aState);

  // Whenever the declared playback state or the guessed playback state changes,
  // we should recompute actual playback state to know if we need to update the
  // virtual control interface.
  void UpdateActualPlaybackState();

  // Return the active media session's declared playback state. If the active
  // media session doesn't exist, return  'None' instead.
  MediaSessionPlaybackState GetCurrentDeclaredPlaybackState() const;

  // This state can match to the `guessed playback state` in the spec [1], it
  // indicates if we have any media element playing within the tab which this
  // controller belongs to. But currently we only take media elements into
  // account, which is different from the way the spec recommends. In addition,
  // We don't support web audio and plugin and not consider audible state of
  // media.
  // [1] https://w3c.github.io/mediasession/#guessed-playback-state
  MediaSessionPlaybackState mGuessedPlaybackState =
      MediaSessionPlaybackState::None;

  // This playback state would be the final playback which can be used to know
  // if the controller is playing or not.
  // https://w3c.github.io/mediasession/#actual-playback-state
  MediaSessionPlaybackState mActualPlaybackState =
      MediaSessionPlaybackState::None;

  nsDataHashtable<nsUint64HashKey, MediaSessionInfo> mMediaSessionInfoMap;
  MediaEventProducer<MediaMetadataBase> mMetadataChangedEvent;
  MediaEventProducer<nsTArray<MediaSessionAction>>
      mSupportedActionsChangedEvent;
  MediaPlaybackStatus mPlaybackStatusDelegate;
};

}  // namespace dom
}  // namespace mozilla

#endif  // DOM_MEDIA_MEDIACONTROL_MEDIASTATUSMANAGER_H_