MediaControlService.h (7280B)
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_MEDIACONTROLSERVICE_H_ 6 #define DOM_MEDIA_MEDIACONTROL_MEDIACONTROLSERVICE_H_ 7 8 #include "AudioFocusManager.h" 9 #include "MediaControlKeyManager.h" 10 #include "MediaController.h" 11 #include "mozilla/dom/MediaControllerBinding.h" 12 #include "nsIObserver.h" 13 #include "nsTArray.h" 14 15 namespace mozilla::dom { 16 17 /** 18 * MediaControlService is an interface to access controllers by providing 19 * controller Id. Everytime when controller becomes active, which means there is 20 * one or more media started in the corresponding browsing context, so now the 21 * controller is actually controlling something in the content process, so it 22 * would be added into the list of the MediaControlService. The controller would 23 * be removed from the list of the MediaControlService when it becomes inactive, 24 * which means no media is playing in the corresponding browsing context. Note 25 * that, a controller can't be added to or remove from the list twice. It should 26 * should have a responsibility to add and remove itself in the proper time. 27 */ 28 class MediaControlService final : public nsIObserver { 29 public: 30 NS_DECL_ISUPPORTS 31 NS_DECL_NSIOBSERVER 32 33 static RefPtr<MediaControlService> GetService(); 34 35 // Currently these following static methods are only being used in testing. 36 static void GenerateMediaControlKey(const GlobalObject& global, 37 MediaControlKey aKey, double aSeekTime); 38 static void GetCurrentActiveMediaMetadata(const GlobalObject& aGlobal, 39 MediaMetadataInit& aMetadata); 40 static MediaSessionPlaybackState GetCurrentMediaSessionPlaybackState( 41 GlobalObject& aGlobal); 42 43 AudioFocusManager& GetAudioFocusManager() { return mAudioFocusManager; } 44 MediaControlKeySource* GetMediaControlKeySource() { 45 return mMediaControlKeyManager; 46 } 47 48 // Use these functions to register/unresgister controller to/from the active 49 // controller list in the service. Return true if the controller is registered 50 // or unregistered sucessfully. 51 bool RegisterActiveMediaController(MediaController* aController); 52 bool UnregisterActiveMediaController(MediaController* aController); 53 uint64_t GetActiveControllersNum() const; 54 55 // This method would be called when the controller changes its playback state. 56 void NotifyControllerPlaybackStateChanged(MediaController* aController); 57 58 // This method is used to help a media controller become a main controller, if 59 // it fits the requirement. 60 void RequestUpdateMainController(MediaController* aController); 61 62 // The main controller is the controller which can receive the media control 63 // key events and would show its metadata to virtual controller interface. 64 MediaController* GetMainController() const; 65 66 /** 67 * These following functions are used for testing only. We use them to 68 * generate fake media control key events, get the media metadata and playback 69 * state from the main controller. 70 */ 71 void GenerateTestMediaControlKey(MediaControlKey aKey, double aSeekValue); 72 MediaMetadataBase GetMainControllerMediaMetadata() const; 73 MediaSessionPlaybackState GetMainControllerPlaybackState() const; 74 75 // Media title that should be used as a fallback. This commonly used 76 // when playing media in private browsing mode and we are trying to avoid 77 // exposing potentially sensitive titles. 78 nsString GetFallbackTitle() const; 79 80 private: 81 MediaControlService(); 82 ~MediaControlService(); 83 84 /** 85 * When there are multiple media controllers existing, we would only choose 86 * one media controller as the main controller which can be controlled by 87 * media control keys event. The latest controller which is added into the 88 * service would become the main controller. 89 * 90 * However, as the main controller would be changed from time to time, so we 91 * create this wrapper to hold a real main controller if it exists. This class 92 * would also observe the playback state of controller in order to update the 93 * playback state of the event source. 94 * 95 * In addition, after finishing bug1592037, we would get the media metadata 96 * from the main controller, and update them to the event source in order to 97 * show those information on the virtual media controller interface on each 98 * platform. 99 */ 100 class ControllerManager final { 101 public: 102 explicit ControllerManager(MediaControlService* aService); 103 ~ControllerManager() = default; 104 105 using MediaKeysArray = nsTArray<MediaControlKey>; 106 using LinkedListControllerPtr = LinkedListElement<RefPtr<MediaController>>*; 107 using ConstLinkedListControllerPtr = 108 const LinkedListElement<RefPtr<MediaController>>*; 109 110 bool AddController(MediaController* aController); 111 bool RemoveController(MediaController* aController); 112 void UpdateMainControllerIfNeeded(MediaController* aController); 113 114 void Shutdown(); 115 116 MediaController* GetMainController() const; 117 bool Contains(MediaController* aController) const; 118 uint64_t GetControllersNum() const; 119 120 // These functions are used for monitoring main controller's status change. 121 void MainControllerPlaybackStateChanged(MediaSessionPlaybackState aState); 122 void MainControllerMetadataChanged(const MediaMetadataBase& aMetadata); 123 124 private: 125 // When applying `eInsertAsMainController`, we would always insert the 126 // element to the tail of the list. Eg. Insert C , [A, B] -> [A, B, C] 127 // When applying `eInsertAsNormalController`, we would insert the element 128 // prior to the element with a higher priority controller. Eg. Insert E and 129 // C and D have higher priority. [A, B, C, D] -> [A, B, E, C, D] 130 enum class InsertOptions { 131 eInsertAsMainController, 132 eInsertAsNormalController, 133 }; 134 135 // Adjust the given controller's order by the insert option. 136 void ReorderGivenController(MediaController* aController, 137 InsertOptions aOption); 138 139 void UpdateMainControllerInternal(MediaController* aController); 140 void ConnectMainControllerEvents(); 141 void DisconnectMainControllerEvents(); 142 143 LinkedList<RefPtr<MediaController>> mControllers; 144 RefPtr<MediaController> mMainController; 145 146 // These member are use to listen main controller's play state changes and 147 // update the playback state to the event source. 148 RefPtr<MediaControlKeySource> mSource; 149 MediaEventListener mMetadataChangedListener; 150 MediaEventListener mSupportedKeysChangedListener; 151 MediaEventListener mFullScreenChangedListener; 152 MediaEventListener mPictureInPictureModeChangedListener; 153 MediaEventListener mPositionChangedListener; 154 }; 155 156 void Init(); 157 void Shutdown(); 158 159 AudioFocusManager mAudioFocusManager; 160 RefPtr<MediaControlKeyManager> mMediaControlKeyManager; 161 RefPtr<MediaControlKeyListener> mMediaKeysHandler; 162 MediaEventProducer<uint64_t> mMediaControllerAmountChangedEvent; 163 UniquePtr<ControllerManager> mControllerManager; 164 nsString mFallbackTitle; 165 166 // Used for telemetry probe. 167 void UpdateTelemetryUsageProbe(); 168 }; 169 170 } // namespace mozilla::dom 171 172 #endif