1 // Copyright 2018 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 SERVICES_MEDIA_SESSION_PUBLIC_CPP_TEST_MOCK_MEDIA_SESSION_H_
6 #define SERVICES_MEDIA_SESSION_PUBLIC_CPP_TEST_MOCK_MEDIA_SESSION_H_
7
8 #include <utility>
9 #include <vector>
10
11 #include "base/component_export.h"
12 #include "base/containers/flat_map.h"
13 #include "base/optional.h"
14 #include "base/run_loop.h"
15 #include "base/unguessable_token.h"
16 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
17 #include "mojo/public/cpp/bindings/receiver_set.h"
18 #include "mojo/public/cpp/bindings/remote_set.h"
19 #include "services/media_session/public/cpp/media_metadata.h"
20 #include "services/media_session/public/mojom/audio_focus.mojom.h"
21 #include "services/media_session/public/mojom/media_controller.mojom.h"
22 #include "services/media_session/public/mojom/media_session.mojom.h"
23
24 namespace base {
25 class UnguessableToken;
26 } // namespace base
27
28 namespace media_session {
29 namespace test {
30
31 // A mock MediaSessionObsever that can be used for waiting for state changes.
COMPONENT_EXPORT(MEDIA_SESSION_TEST_SUPPORT_CPP)32 class COMPONENT_EXPORT(MEDIA_SESSION_TEST_SUPPORT_CPP)
33 MockMediaSessionMojoObserver : public mojom::MediaSessionObserver {
34 public:
35 explicit MockMediaSessionMojoObserver(mojom::MediaSession& media_session);
36
37 ~MockMediaSessionMojoObserver() override;
38
39 // mojom::MediaSessionObserver overrides.
40 void MediaSessionInfoChanged(mojom::MediaSessionInfoPtr session) override;
41 void MediaSessionMetadataChanged(
42 const base::Optional<MediaMetadata>& metadata) override;
43 void MediaSessionActionsChanged(
44 const std::vector<mojom::MediaSessionAction>& actions) override;
45 void MediaSessionImagesChanged(
46 const base::flat_map<mojom::MediaSessionImageType,
47 std::vector<MediaImage>>& images) override;
48 void MediaSessionPositionChanged(
49 const base::Optional<media_session::MediaPosition>& position) override;
50
51 void WaitForState(mojom::MediaSessionInfo::SessionState wanted_state);
52 void WaitForPlaybackState(mojom::MediaPlaybackState wanted_state);
53 void WaitForAudioVideoState(mojom::MediaAudioVideoState wanted_state);
54 void WaitForControllable(bool is_controllable);
55
56 void WaitForEmptyMetadata();
57 void WaitForExpectedMetadata(const MediaMetadata& metadata);
58
59 void WaitForEmptyActions();
60 void WaitForExpectedActions(
61 const std::set<mojom::MediaSessionAction>& actions);
62
63 void WaitForExpectedImagesOfType(mojom::MediaSessionImageType type,
64 const std::vector<MediaImage>& images);
65
66 void WaitForEmptyPosition();
67
68 // Blocks until notified about MediaPosition changing to one matching
69 // |position|.
70 void WaitForExpectedPosition(const MediaPosition& position);
71
72 // Blocks until notified about MediaPosition changing to one matching
73 // |position|, where media time is required to be equal to or greater than
74 // the media time of |position|. Returns the media time actually reported
75 // with MediaPosition.
76 base::TimeDelta WaitForExpectedPositionAtLeast(const MediaPosition& position);
77
78 const mojom::MediaSessionInfoPtr& session_info() const {
79 return session_info_;
80 }
81
82 const base::Optional<base::Optional<MediaMetadata>>& session_metadata()
83 const {
84 return session_metadata_;
85 }
86
87 const std::set<mojom::MediaSessionAction>& actions() const {
88 return *session_actions_;
89 }
90
91 const base::Optional<base::Optional<MediaPosition>>& session_position() {
92 return session_position_;
93 }
94
95 private:
96 void StartWaiting();
97
98 mojom::MediaSessionInfoPtr session_info_;
99 base::Optional<base::Optional<MediaMetadata>> session_metadata_;
100 base::Optional<std::set<mojom::MediaSessionAction>> session_actions_;
101 base::Optional<
102 base::flat_map<mojom::MediaSessionImageType, std::vector<MediaImage>>>
103 session_images_;
104 base::Optional<base::Optional<MediaPosition>> session_position_;
105 bool waiting_for_empty_position_ = false;
106
107 base::Optional<MediaMetadata> expected_metadata_;
108 base::Optional<std::set<mojom::MediaSessionAction>> expected_actions_;
109 base::Optional<bool> expected_controllable_;
110 base::Optional<
111 std::pair<mojom::MediaSessionImageType, std::vector<MediaImage>>>
112 expected_images_of_type_;
113 base::Optional<MediaPosition> expected_position_;
114 base::Optional<MediaPosition> minimum_expected_position_;
115 bool waiting_for_empty_metadata_ = false;
116
117 base::Optional<mojom::MediaSessionInfo::SessionState> wanted_state_;
118 base::Optional<mojom::MediaPlaybackState> wanted_playback_state_;
119 base::Optional<mojom::MediaAudioVideoState> wanted_audio_video_state_;
120 std::unique_ptr<base::RunLoop> run_loop_;
121
122 mojo::Receiver<mojom::MediaSessionObserver> receiver_{this};
123 };
124
125 // A mock MediaSession that can be used for interacting with the Media Session
126 // service during tests.
COMPONENT_EXPORT(MEDIA_SESSION_TEST_SUPPORT_CPP)127 class COMPONENT_EXPORT(MEDIA_SESSION_TEST_SUPPORT_CPP) MockMediaSession
128 : public mojom::MediaSession {
129 public:
130 MockMediaSession();
131 explicit MockMediaSession(bool force_duck);
132
133 ~MockMediaSession() override;
134
135 // mojom::MediaSession overrides.
136 void Suspend(SuspendType type) override;
137 void Resume(SuspendType type) override;
138 void StartDucking() override;
139 void StopDucking() override;
140 void GetMediaSessionInfo(GetMediaSessionInfoCallback callback) override;
141 void AddObserver(
142 mojo::PendingRemote<mojom::MediaSessionObserver> observer) override;
143 void GetDebugInfo(GetDebugInfoCallback callback) override;
144 void PreviousTrack() override;
145 void NextTrack() override;
146 void SkipAd() override {}
147 void Seek(base::TimeDelta seek_time) override;
148 void Stop(SuspendType type) override;
149 void GetMediaImageBitmap(const MediaImage& image,
150 int minimum_size_px,
151 int desired_size_px,
152 GetMediaImageBitmapCallback callback) override;
153 void SeekTo(base::TimeDelta seek_time) override;
154 void ScrubTo(base::TimeDelta scrub_to) override;
155 void EnterPictureInPicture() override;
156 void ExitPictureInPicture() override;
157 void SetAudioSinkId(const base::Optional<std::string>& id) override {}
158
159 void SetIsControllable(bool value);
160 void SetPreferStop(bool value) { prefer_stop_ = value; }
161
162 void AbandonAudioFocusFromClient();
163
164 base::UnguessableToken RequestAudioFocusFromService(
165 mojo::Remote<mojom::AudioFocusManager>& service,
166 mojom::AudioFocusType audio_foucs_type);
167
168 bool RequestGroupedAudioFocusFromService(
169 const base::UnguessableToken& request_id,
170 mojo::Remote<mojom::AudioFocusManager>& service,
171 mojom::AudioFocusType audio_focus_type,
172 const base::UnguessableToken& group_id);
173
174 mojom::MediaSessionInfo::SessionState GetState() const;
175
176 mojom::AudioFocusRequestClient* audio_focus_request() const {
177 return afr_client_.get();
178 }
179 void FlushForTesting();
180
181 void SimulateMetadataChanged(const base::Optional<MediaMetadata>& metadata);
182 void SimulatePositionChanged(const base::Optional<MediaPosition>& position);
183
184 void ClearAllImages();
185 void SetImagesOfType(mojom::MediaSessionImageType type,
186 const std::vector<MediaImage>& images);
187
188 void EnableAction(mojom::MediaSessionAction action);
189 void DisableAction(mojom::MediaSessionAction action);
190
191 int prev_track_count() const { return prev_track_count_; }
192 int next_track_count() const { return next_track_count_; }
193 int add_observer_count() const { return add_observer_count_; }
194 int seek_count() const { return seek_count_; }
195 int seek_to_count() const { return seek_to_count_; }
196
197 bool is_scrubbing() const { return is_scrubbing_; }
198 const GURL& last_image_src() const { return last_image_src_; }
199
200 const base::UnguessableToken& request_id() const { return request_id_; }
201
202 private:
203 void SetState(mojom::MediaSessionInfo::SessionState);
204 void NotifyObservers();
205 mojom::MediaSessionInfoPtr GetMediaSessionInfoSync() const;
206 void NotifyActionObservers();
207
208 void RequestAudioFocusFromClient(mojom::AudioFocusType audio_focus_type);
209
210 mojo::Remote<mojom::AudioFocusRequestClient> afr_client_;
211
212 base::UnguessableToken request_id_;
213
214 const bool force_duck_ = false;
215 bool is_ducking_ = false;
216 bool is_controllable_ = false;
217 bool is_scrubbing_ = false;
218 bool prefer_stop_ = false;
219
220 int prev_track_count_ = 0;
221 int next_track_count_ = 0;
222 int add_observer_count_ = 0;
223 int seek_count_ = 0;
224 int seek_to_count_ = 0;
225
226 std::set<mojom::MediaSessionAction> actions_;
227
228 mojom::MediaSessionInfo::SessionState state_ =
229 mojom::MediaSessionInfo::SessionState::kInactive;
230
231 base::flat_map<mojom::MediaSessionImageType, std::vector<MediaImage>> images_;
232 GURL last_image_src_;
233
234 mojo::ReceiverSet<mojom::MediaSession> receivers_;
235
236 mojo::RemoteSet<mojom::MediaSessionObserver> observers_;
237
238 DISALLOW_COPY_AND_ASSIGN(MockMediaSession);
239 };
240
241 } // namespace test
242 } // namespace media_session
243
244 #endif // SERVICES_MEDIA_SESSION_PUBLIC_CPP_TEST_MOCK_MEDIA_SESSION_H_
245