tor-browser

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

MediaController.h (7981B)


      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #ifndef DOM_MEDIA_MEDIACONTROL_MEDIACONTROLLER_H_
      8 #define DOM_MEDIA_MEDIACONTROL_MEDIACONTROLLER_H_
      9 
     10 #include "MediaEventSource.h"
     11 #include "MediaPlaybackStatus.h"
     12 #include "MediaStatusManager.h"
     13 #include "mozilla/DOMEventTargetHelper.h"
     14 #include "mozilla/LinkedList.h"
     15 #include "mozilla/dom/MediaControllerBinding.h"
     16 #include "mozilla/dom/MediaSession.h"
     17 #include "nsISupportsImpl.h"
     18 #include "nsITimer.h"
     19 
     20 namespace mozilla::dom {
     21 
     22 class BrowsingContext;
     23 
     24 /**
     25 * IMediaController is an interface which includes control related methods and
     26 * methods used to know its playback state.
     27 */
     28 class IMediaController {
     29 public:
     30  NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
     31 
     32  // Focus the window currently playing media.
     33  virtual void Focus() = 0;
     34  virtual void Play() = 0;
     35  virtual void Pause() = 0;
     36  virtual void Stop() = 0;
     37  virtual void PrevTrack() = 0;
     38  virtual void NextTrack() = 0;
     39  virtual void SeekBackward(double aSeekOffset) = 0;
     40  virtual void SeekForward(double aSeekOffset) = 0;
     41  virtual void SkipAd() = 0;
     42  virtual void SeekTo(double aSeekTime, bool aFastSeek) = 0;
     43 
     44  // Return the ID of the top level browsing context within a tab.
     45  virtual uint64_t Id() const = 0;
     46  virtual bool IsAudible() const = 0;
     47  virtual bool IsPlaying() const = 0;
     48  virtual bool IsActive() const = 0;
     49 };
     50 
     51 /**
     52 * MediaController is a class, which is used to control all media within a tab.
     53 * It can only be used in Chrome process and the controlled media are usually
     54 * in the content process (unless we disable e10s).
     55 *
     56 * Each tab would have only one media controller, they are 1-1 corresponding
     57 * relationship, we use tab's top-level browsing context ID to initialize the
     58 * controller and use that as its ID.
     59 *
     60 * The controller would be activated when its controlled media starts and
     61 * becomes audible. After the controller is activated, then we can use its
     62 * controlling methods, such as `Play()`, `Pause()` to control the media within
     63 * the tab.
     64 *
     65 * If there is at least one controlled media playing in the tab, then we would
     66 * say the controller is `playing`. If there is at least one controlled media is
     67 * playing and audible, then we would say the controller is `audible`.
     68 *
     69 * Note that, if we don't enable audio competition, then we might have multiple
     70 * tabs playing media at the same time, we can use the ID to query the specific
     71 * controller from `MediaControlService`.
     72 */
     73 class MediaController final : public DOMEventTargetHelper,
     74                              public IMediaController,
     75                              public LinkedListElement<RefPtr<MediaController>>,
     76                              public MediaStatusManager,
     77                              public nsITimerCallback,
     78                              public nsINamed {
     79 public:
     80  NS_DECL_ISUPPORTS_INHERITED
     81  NS_DECL_NSITIMERCALLBACK
     82  NS_DECL_NSINAMED
     83  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MediaController,
     84                                                         DOMEventTargetHelper)
     85  explicit MediaController(uint64_t aBrowsingContextId);
     86 
     87  // WebIDL methods
     88  nsISupports* GetParentObject() const;
     89  JSObject* WrapObject(JSContext* aCx,
     90                       JS::Handle<JSObject*> aGivenProto) override;
     91  void GetSupportedKeys(nsTArray<MediaControlKey>& aRetVal) const;
     92  void GetMetadata(MediaMetadataInit& aMetadata, ErrorResult& aRv);
     93  IMPL_EVENT_HANDLER(activated);
     94  IMPL_EVENT_HANDLER(deactivated);
     95  IMPL_EVENT_HANDLER(metadatachange);
     96  IMPL_EVENT_HANDLER(supportedkeyschange);
     97  IMPL_EVENT_HANDLER(playbackstatechange);
     98  IMPL_EVENT_HANDLER(positionstatechange);
     99 
    100  // IMediaController's methods
    101  void Focus() override;
    102  void Play() override;
    103  void Pause() override;
    104  void Stop() override;
    105  void PrevTrack() override;
    106  void NextTrack() override;
    107  void SeekBackward(double aSeekOffset) override;
    108  void SeekForward(double aSeekOffset) override;
    109  void SkipAd() override;
    110  void SeekTo(double aSeekTime, bool aFastSeek) override;
    111 
    112  uint64_t Id() const override;
    113  bool IsAudible() const override;
    114  bool IsPlaying() const override;
    115  bool IsActive() const override;
    116 
    117  // IMediaInfoUpdater's methods
    118  void NotifyMediaPlaybackChanged(uint64_t aBrowsingContextId,
    119                                  MediaPlaybackState aState) override;
    120  void NotifyMediaAudibleChanged(uint64_t aBrowsingContextId,
    121                                 MediaAudibleState aState) override;
    122  void SetIsInPictureInPictureMode(uint64_t aBrowsingContextId,
    123                                   bool aIsInPictureInPictureMode) override;
    124  void NotifyMediaFullScreenState(uint64_t aBrowsingContextId,
    125                                  bool aIsInFullScreen) override;
    126 
    127  // Calling this method explicitly would mark this controller as deprecated,
    128  // then calling any its method won't take any effect.
    129  void Shutdown();
    130 
    131  // This event would be notified media controller's supported media keys
    132  // change.
    133  MediaEventSource<nsTArray<MediaControlKey>>& SupportedKeysChangedEvent() {
    134    return mSupportedKeysChangedEvent;
    135  }
    136 
    137  MediaEventSource<bool>& FullScreenChangedEvent() {
    138    return mFullScreenChangedEvent;
    139  }
    140 
    141  MediaEventSource<bool>& PictureInPictureModeChangedEvent() {
    142    return mPictureInPictureModeChangedEvent;
    143  }
    144 
    145  CopyableTArray<MediaControlKey> GetSupportedMediaKeys() const;
    146 
    147  bool IsBeingUsedInPIPModeOrFullscreen() const;
    148 
    149  // These methods are used to select/unselect the media controller as a main
    150  // controller.
    151  void Select() const;
    152  void Unselect() const;
    153 
    154 private:
    155  ~MediaController();
    156  void HandleActualPlaybackStateChanged();
    157  void UpdateMediaControlActionToContentMediaIfNeeded(
    158      const MediaControlAction& aAction);
    159  void HandleSupportedMediaSessionActionsChanged(
    160      const nsTArray<MediaSessionAction>& aSupportedAction);
    161 
    162  void HandlePositionStateChanged(const Maybe<PositionState>& aState);
    163  void HandleMetadataChanged(const MediaMetadataBase& aMetadata);
    164 
    165  // This would register controller to the media control service that takes a
    166  // responsibility to manage all active controllers.
    167  void Activate();
    168 
    169  // This would unregister controller from the media control service.
    170  void Deactivate();
    171 
    172  void UpdateActivatedStateIfNeeded();
    173  bool ShouldActivateController() const;
    174  bool ShouldDeactivateController() const;
    175 
    176  void UpdateDeactivationTimerIfNeeded();
    177 
    178  void DispatchAsyncEvent(const nsAString& aName);
    179  void DispatchAsyncEvent(already_AddRefed<Event> aEvent);
    180 
    181  bool IsMainController() const;
    182  void ForceToBecomeMainControllerIfNeeded();
    183  bool ShouldRequestForMainController() const;
    184 
    185  bool ShouldPropagateActionToAllContexts(
    186      const MediaControlAction& aAction) const;
    187 
    188  bool mIsActive = false;
    189  bool mShutdown = false;
    190  bool mIsInPictureInPictureMode = false;
    191  bool mIsInFullScreenMode = false;
    192 
    193  // We would monitor the change of media session actions and convert them to
    194  // the media keys, then determine the supported media keys.
    195  MediaEventListener mSupportedActionsChangedListener;
    196  MediaEventProducer<nsTArray<MediaControlKey>> mSupportedKeysChangedEvent;
    197 
    198  MediaEventListener mPlaybackChangedListener;
    199  MediaEventListener mPositionStateChangedListener;
    200  MediaEventListener mMetadataChangedListener;
    201 
    202  MediaEventProducer<bool> mFullScreenChangedEvent;
    203  MediaEventProducer<bool> mPictureInPictureModeChangedEvent;
    204  // Use copyable array so that we can use the result as a parameter for the
    205  // media event.
    206  CopyableTArray<MediaControlKey> mSupportedKeys;
    207  // Timer to deactivate the controller if the time of being paused exceeds the
    208  // threshold of time.
    209  nsCOMPtr<nsITimer> mDeactivationTimer;
    210 };
    211 
    212 }  // namespace mozilla::dom
    213 
    214 #endif