1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef ASH_MEDIA_MEDIA_CONTROLLER_IMPL_H_
6 #define ASH_MEDIA_MEDIA_CONTROLLER_IMPL_H_
7 
8 #include "ash/ash_export.h"
9 #include "ash/public/cpp/media_controller.h"
10 #include "base/macros.h"
11 #include "base/observer_list.h"
12 #include "components/account_id/account_id.h"
13 #include "mojo/public/cpp/bindings/receiver.h"
14 #include "mojo/public/cpp/bindings/remote.h"
15 #include "services/media_session/public/mojom/media_controller.mojom.h"
16 
17 class PrefRegistrySimple;
18 
19 namespace ash {
20 
21 class MediaClient;
22 
23 // Forwards notifications from the MediaController to observers.
24 class MediaCaptureObserver {
25  public:
26   // Called when media capture state has changed.
OnMediaCaptureChanged(const base::flat_map<AccountId,MediaCaptureState> & capture_states)27   virtual void OnMediaCaptureChanged(
28       const base::flat_map<AccountId, MediaCaptureState>& capture_states) {}
29   // Called when a VM's media capture state has changed.
OnVmMediaCaptureChanged(MediaCaptureState state)30   virtual void OnVmMediaCaptureChanged(MediaCaptureState state) {}
31 
32  protected:
~MediaCaptureObserver()33   virtual ~MediaCaptureObserver() {}
34 };
35 
36 // Provides the MediaController interface to the outside world. This lets a
37 // consumer of ash provide a MediaClient, which we will dispatch to if one has
38 // been provided to us.
39 class ASH_EXPORT MediaControllerImpl
40     : public MediaController,
41       public media_session::mojom::MediaControllerObserver {
42  public:
43   MediaControllerImpl();
44   ~MediaControllerImpl() override;
45 
46   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
47 
48   // Determine if lock screen media keys are enabled.
49   bool AreLockScreenMediaKeysEnabled() const;
50   void SetMediaControlsDismissed(bool media_controls_dismissed);
51 
52   void AddObserver(MediaCaptureObserver* observer);
53   void RemoveObserver(MediaCaptureObserver* observer);
54 
55   // MediaController:
56   void SetClient(MediaClient* client) override;
57   void SetForceMediaClientKeyHandling(bool enabled) override;
58   void NotifyCaptureState(const base::flat_map<AccountId, MediaCaptureState>&
59                               capture_states) override;
60   void NotifyVmCaptureState(MediaCaptureState capture_state) override;
61 
62   // If media session accelerators are enabled then these methods will use the
63   // media session service to control playback. Otherwise it will forward to
64   // |client_|.
65   void HandleMediaPlayPause();
66   void HandleMediaPlay();
67   void HandleMediaPause();
68   void HandleMediaStop();
69   void HandleMediaNextTrack();
70   void HandleMediaPrevTrack();
71   void HandleMediaSeekBackward();
72   void HandleMediaSeekForward();
73 
74   // Methods that forward to |client_|.
75   void RequestCaptureState();
76   void SuspendMediaSessions();
77 
78   // media_session::mojom::MediaControllerObserver:
79   void MediaSessionInfoChanged(
80       media_session::mojom::MediaSessionInfoPtr session_info) override;
MediaSessionMetadataChanged(const base::Optional<media_session::MediaMetadata> & metadata)81   void MediaSessionMetadataChanged(
82       const base::Optional<media_session::MediaMetadata>& metadata) override {}
83   void MediaSessionActionsChanged(
84       const std::vector<media_session::mojom::MediaSessionAction>& actions)
85       override;
MediaSessionChanged(const base::Optional<base::UnguessableToken> & request_id)86   void MediaSessionChanged(
87       const base::Optional<base::UnguessableToken>& request_id) override {}
MediaSessionPositionChanged(const base::Optional<media_session::MediaPosition> & position)88   void MediaSessionPositionChanged(
89       const base::Optional<media_session::MediaPosition>& position) override {}
90 
91  private:
92   friend class MediaControllerTest;
93   friend class MediaSessionAcceleratorTest;
94   friend class MultiProfileMediaTrayItemTest;
95   FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
96                            MediaGlobalAccelerators_NextTrack);
97   FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
98                            MediaGlobalAccelerators_Play);
99   FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
100                            MediaGlobalAccelerators_Pause);
101   FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
102                            MediaGlobalAccelerators_PrevTrack);
103   FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
104                            MediaGlobalAccelerators_UpdateAction_Disable);
105   FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
106                            MediaGlobalAccelerators_UpdateAction_Enable);
107   FRIEND_TEST_ALL_PREFIXES(MediaSessionAcceleratorTest,
108                            MediaGlobalAccelerators_UpdateForceKeyHandling);
109 
110   void SetMediaSessionControllerForTest(
111       mojo::Remote<media_session::mojom::MediaController> controller);
112 
113   void FlushForTesting();
114 
115   // Returns a pointer to the active media session controller.
116   media_session::mojom::MediaController* GetMediaSessionController();
117 
118   void OnMediaSessionControllerError();
119 
120   void BindMediaControllerObserver();
121 
122   // Returns true if we should use the media session service for key handling.
123   bool ShouldUseMediaSession();
124 
125   void ResetForceMediaClientKeyHandling();
126 
127   // Whether the active media session currently supports any action that has a
128   // media key.
129   bool supported_media_session_action_ = false;
130 
131   // The info about the current media session. It will be null if there is not
132   // a current session.
133   media_session::mojom::MediaSessionInfoPtr media_session_info_;
134 
135   // If true then the media keys should be forwarded to the client instead of
136   // being handled in ash.
137   bool force_media_client_key_handling_ = false;
138 
139   // Whether the lock screen media controls are dismissed.
140   bool media_controls_dismissed_ = false;
141 
142   // Mojo pointer to the active media session controller.
143   mojo::Remote<media_session::mojom::MediaController>
144       media_session_controller_remote_;
145 
146   mojo::Receiver<media_session::mojom::MediaControllerObserver>
147       media_controller_observer_receiver_{this};
148 
149   MediaClient* client_ = nullptr;
150 
151   base::ObserverList<MediaCaptureObserver>::Unchecked observers_;
152 
153   DISALLOW_COPY_AND_ASSIGN(MediaControllerImpl);
154 };
155 
156 }  // namespace ash
157 
158 #endif  // ASH_MEDIA_MEDIA_CONTROLLER_IMPL_H_
159