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 #include "services/media_session/media_controller.h"
6
7 #include <memory>
8 #include <utility>
9 #include <vector>
10
11 #include "base/run_loop.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/test/task_environment.h"
14 #include "base/time/time.h"
15 #include "base/unguessable_token.h"
16 #include "mojo/public/cpp/bindings/remote.h"
17 #include "services/media_session/media_session_service.h"
18 #include "services/media_session/public/cpp/media_metadata.h"
19 #include "services/media_session/public/cpp/test/mock_media_session.h"
20 #include "services/media_session/public/cpp/test/test_media_controller.h"
21 #include "services/media_session/public/mojom/constants.mojom.h"
22 #include "services/media_session/public/mojom/media_session.mojom.h"
23 #include "services/media_session/public/mojom/media_session_service.mojom.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25
26 namespace media_session {
27
28 class MediaControllerTest : public testing::Test {
29 public:
30 MediaControllerTest() = default;
31
SetUp()32 void SetUp() override {
33 // Create an instance of the MediaSessionService and bind some interfaces.
34 service_ = std::make_unique<MediaSessionService>(
35 service_remote_.BindNewPipeAndPassReceiver());
36 service_remote_->BindAudioFocusManager(
37 audio_focus_remote_.BindNewPipeAndPassReceiver());
38 service_remote_->BindMediaControllerManager(
39 controller_manager_remote_.BindNewPipeAndPassReceiver());
40
41 controller_manager_remote_->CreateActiveMediaController(
42 media_controller_remote_.BindNewPipeAndPassReceiver());
43 controller_manager_remote_.FlushForTesting();
44
45 audio_focus_remote_->SetEnforcementMode(
46 mojom::EnforcementMode::kSingleSession);
47 audio_focus_remote_.FlushForTesting();
48 }
49
TearDown()50 void TearDown() override {
51 // Run pending tasks.
52 base::RunLoop().RunUntilIdle();
53 }
54
RequestAudioFocus(test::MockMediaSession & session,mojom::AudioFocusType type)55 void RequestAudioFocus(test::MockMediaSession& session,
56 mojom::AudioFocusType type) {
57 session.RequestAudioFocusFromService(audio_focus_remote_, type);
58 }
59
controller()60 mojo::Remote<mojom::MediaController>& controller() {
61 return media_controller_remote_;
62 }
63
manager()64 mojo::Remote<mojom::MediaControllerManager>& manager() {
65 return controller_manager_remote_;
66 }
67
GetImageObserverCount(const MediaController & controller)68 static size_t GetImageObserverCount(const MediaController& controller) {
69 return controller.image_observers_.size();
70 }
71
72 private:
73 base::test::TaskEnvironment task_environment_;
74 std::unique_ptr<MediaSessionService> service_;
75 mojo::Remote<mojom::MediaSessionService> service_remote_;
76 mojo::Remote<mojom::AudioFocusManager> audio_focus_remote_;
77 mojo::Remote<mojom::MediaController> media_controller_remote_;
78 mojo::Remote<mojom::MediaControllerManager> controller_manager_remote_;
79
80 DISALLOW_COPY_AND_ASSIGN(MediaControllerTest);
81 };
82
TEST_F(MediaControllerTest,ActiveController_Suspend)83 TEST_F(MediaControllerTest, ActiveController_Suspend) {
84 test::MockMediaSession media_session;
85 media_session.SetIsControllable(true);
86
87 {
88 test::MockMediaSessionMojoObserver observer(media_session);
89 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
90 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
91 }
92
93 {
94 test::MockMediaSessionMojoObserver observer(media_session);
95 controller()->Suspend();
96 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
97 }
98 }
99
TEST_F(MediaControllerTest,ActiveController_Multiple_Abandon_Top)100 TEST_F(MediaControllerTest, ActiveController_Multiple_Abandon_Top) {
101 test::MockMediaSession media_session_1;
102 test::MockMediaSession media_session_2;
103
104 media_session_1.SetIsControllable(true);
105 media_session_2.SetIsControllable(true);
106
107 {
108 test::MockMediaSessionMojoObserver observer(media_session_1);
109 RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
110 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
111 }
112
113 {
114 test::MockMediaSessionMojoObserver observer_1(media_session_1);
115 test::MockMediaSessionMojoObserver observer_2(media_session_2);
116
117 RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGain);
118
119 observer_1.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
120 observer_2.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
121 }
122
123 media_session_2.AbandonAudioFocusFromClient();
124
125 {
126 test::MockMediaSessionMojoObserver observer(media_session_1);
127 controller()->Resume();
128 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
129 }
130 }
131
TEST_F(MediaControllerTest,ActiveController_Multiple_Abandon_UnderNonControllable)132 TEST_F(MediaControllerTest,
133 ActiveController_Multiple_Abandon_UnderNonControllable) {
134 test::MockMediaSession media_session_1;
135 test::MockMediaSession media_session_2;
136 test::MockMediaSession media_session_3;
137
138 media_session_1.SetIsControllable(true);
139 media_session_2.SetIsControllable(true);
140
141 {
142 test::MockMediaSessionMojoObserver observer(media_session_1);
143 RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
144 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
145 }
146
147 {
148 test::MockMediaSessionMojoObserver observer_1(media_session_1);
149 test::MockMediaSessionMojoObserver observer_2(media_session_2);
150
151 RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGain);
152
153 observer_1.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
154 observer_2.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
155 }
156
157 {
158 test::MockMediaSessionMojoObserver observer_2(media_session_2);
159 test::MockMediaSessionMojoObserver observer_3(media_session_3);
160
161 RequestAudioFocus(media_session_3, mojom::AudioFocusType::kGain);
162
163 observer_2.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
164 observer_3.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
165 }
166
167 media_session_2.AbandonAudioFocusFromClient();
168
169 {
170 test::MockMediaSessionMojoObserver observer(media_session_1);
171 controller()->Resume();
172 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
173 }
174 }
175
TEST_F(MediaControllerTest,ActiveController_Multiple_Controllable)176 TEST_F(MediaControllerTest, ActiveController_Multiple_Controllable) {
177 test::MockMediaSession media_session_1;
178 test::MockMediaSession media_session_2;
179
180 media_session_1.SetIsControllable(true);
181 media_session_2.SetIsControllable(true);
182
183 {
184 test::MockMediaSessionMojoObserver observer(media_session_1);
185 RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
186 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
187 }
188
189 {
190 test::MockMediaSessionMojoObserver observer_1(media_session_1);
191 test::MockMediaSessionMojoObserver observer_2(media_session_2);
192
193 RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGain);
194
195 observer_1.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
196 observer_2.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
197 }
198
199 {
200 test::MockMediaSessionMojoObserver observer(media_session_2);
201 controller()->Suspend();
202 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
203 }
204 }
205
TEST_F(MediaControllerTest,ActiveController_Multiple_NonControllable)206 TEST_F(MediaControllerTest, ActiveController_Multiple_NonControllable) {
207 test::MockMediaSession media_session_1;
208 test::MockMediaSession media_session_2;
209
210 media_session_1.SetIsControllable(true);
211
212 {
213 test::MockMediaSessionMojoObserver observer(media_session_1);
214 RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
215 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
216 }
217
218 EXPECT_EQ(2, media_session_1.add_observer_count());
219
220 {
221 test::MockMediaSessionMojoObserver observer_1(media_session_1);
222 test::MockMediaSessionMojoObserver observer_2(media_session_2);
223
224 RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGain);
225
226 observer_1.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
227 observer_2.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
228 }
229
230 // The top session has changed but the controller is still bound to
231 // |media_session_1|. We should make sure we do not add an observer if we
232 // already have one.
233 EXPECT_EQ(3, media_session_1.add_observer_count());
234
235 {
236 test::MockMediaSessionMojoObserver observer(media_session_1);
237 controller()->Resume();
238 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
239 }
240
241 EXPECT_EQ(4, media_session_1.add_observer_count());
242 }
243
TEST_F(MediaControllerTest,ActiveController_Multiple_UpdateControllable)244 TEST_F(MediaControllerTest, ActiveController_Multiple_UpdateControllable) {
245 test::MockMediaSession media_session_1;
246 test::MockMediaSession media_session_2;
247
248 media_session_1.SetIsControllable(true);
249 media_session_2.SetIsControllable(true);
250
251 EXPECT_EQ(0, media_session_1.add_observer_count());
252 EXPECT_EQ(0, media_session_2.add_observer_count());
253
254 {
255 test::MockMediaSessionMojoObserver observer(media_session_1);
256 RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
257 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
258 }
259
260 EXPECT_EQ(2, media_session_1.add_observer_count());
261 EXPECT_EQ(0, media_session_2.add_observer_count());
262
263 {
264 test::MockMediaSessionMojoObserver observer(media_session_2);
265 RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGainTransient);
266 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
267 }
268
269 EXPECT_EQ(2, media_session_1.add_observer_count());
270 EXPECT_EQ(2, media_session_2.add_observer_count());
271
272 media_session_2.SetIsControllable(false);
273 media_session_2.FlushForTesting();
274
275 EXPECT_EQ(3, media_session_1.add_observer_count());
276 EXPECT_EQ(2, media_session_2.add_observer_count());
277
278 media_session_1.SetIsControllable(false);
279 media_session_1.FlushForTesting();
280
281 EXPECT_EQ(3, media_session_1.add_observer_count());
282 EXPECT_EQ(2, media_session_2.add_observer_count());
283 }
284
TEST_F(MediaControllerTest,ActiveController_Suspend_Noop)285 TEST_F(MediaControllerTest, ActiveController_Suspend_Noop) {
286 controller()->Suspend();
287 }
288
TEST_F(MediaControllerTest,ActiveController_Suspend_Noop_Abandoned)289 TEST_F(MediaControllerTest, ActiveController_Suspend_Noop_Abandoned) {
290 test::MockMediaSession media_session;
291 media_session.SetIsControllable(true);
292
293 {
294 test::MockMediaSessionMojoObserver observer(media_session);
295 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
296 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
297 }
298
299 media_session.AbandonAudioFocusFromClient();
300
301 controller()->Suspend();
302
303 {
304 test::MockMediaSessionMojoObserver observer(media_session);
305 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
306 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
307 }
308 }
309
TEST_F(MediaControllerTest,ActiveController_SuspendResume)310 TEST_F(MediaControllerTest, ActiveController_SuspendResume) {
311 test::MockMediaSession media_session;
312 media_session.SetIsControllable(true);
313
314 {
315 test::MockMediaSessionMojoObserver observer(media_session);
316 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
317 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
318 }
319
320 {
321 test::MockMediaSessionMojoObserver observer(media_session);
322 controller()->Suspend();
323 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
324 }
325
326 {
327 test::MockMediaSessionMojoObserver observer(media_session);
328 controller()->Resume();
329 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
330 }
331 }
332
TEST_F(MediaControllerTest,ActiveController_ToggleSuspendResume_Playing)333 TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Playing) {
334 test::MockMediaSession media_session;
335 media_session.SetIsControllable(true);
336
337 {
338 test::MockMediaSessionMojoObserver observer(media_session);
339 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
340 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
341 }
342
343 {
344 test::MockMediaSessionMojoObserver observer(media_session);
345 controller()->ToggleSuspendResume();
346 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
347 }
348 }
349
TEST_F(MediaControllerTest,ActiveController_ToggleSuspendResume_Ducked)350 TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Ducked) {
351 test::MockMediaSession media_session;
352 media_session.SetIsControllable(true);
353
354 {
355 test::MockMediaSessionMojoObserver observer(media_session);
356 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
357 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
358 }
359
360 {
361 test::MockMediaSessionMojoObserver observer(media_session);
362 media_session.StartDucking();
363 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kDucking);
364 }
365
366 {
367 test::MockMediaSessionMojoObserver observer(media_session);
368 controller()->ToggleSuspendResume();
369 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
370 }
371 }
372
TEST_F(MediaControllerTest,ActiveController_ToggleSuspendResume_Inactive)373 TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Inactive) {
374 test::MockMediaSession media_session;
375 media_session.SetIsControllable(true);
376
377 {
378 test::MockMediaSessionMojoObserver observer(media_session);
379 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
380 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
381 }
382
383 {
384 test::MockMediaSessionMojoObserver observer(media_session);
385 media_session.Stop(mojom::MediaSession::SuspendType::kUI);
386 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kInactive);
387 }
388
389 {
390 test::MockMediaSessionMojoObserver observer(media_session);
391 controller()->ToggleSuspendResume();
392 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
393 }
394 }
395
TEST_F(MediaControllerTest,ActiveController_ToggleSuspendResume_Paused)396 TEST_F(MediaControllerTest, ActiveController_ToggleSuspendResume_Paused) {
397 test::MockMediaSession media_session;
398 media_session.SetIsControllable(true);
399
400 {
401 test::MockMediaSessionMojoObserver observer(media_session);
402 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
403 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
404 }
405
406 {
407 test::MockMediaSessionMojoObserver observer(media_session);
408 controller()->Suspend();
409 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
410 }
411
412 {
413 test::MockMediaSessionMojoObserver observer(media_session);
414 controller()->ToggleSuspendResume();
415 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
416 }
417 }
418
TEST_F(MediaControllerTest,ActiveController_Observer_StateTransition)419 TEST_F(MediaControllerTest, ActiveController_Observer_StateTransition) {
420 test::MockMediaSession media_session_1;
421 test::MockMediaSession media_session_2;
422
423 media_session_1.SetIsControllable(true);
424 media_session_2.SetIsControllable(true);
425
426 {
427 test::MockMediaSessionMojoObserver observer(media_session_1);
428 RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
429 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
430 }
431
432 {
433 test::TestMediaControllerObserver observer(controller());
434 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
435 }
436
437 {
438 test::TestMediaControllerObserver observer(controller());
439 controller()->Suspend();
440 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kSuspended);
441 }
442
443 {
444 test::TestMediaControllerObserver observer(controller());
445 RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGain);
446 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
447 }
448
449 {
450 test::MockMediaSessionMojoObserver observer(media_session_1);
451 media_session_1.StartDucking();
452 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kDucking);
453 }
454
455 {
456 test::TestMediaControllerObserver observer(controller());
457 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
458 }
459 }
460
TEST_F(MediaControllerTest,ActiveController_PreviousTrack)461 TEST_F(MediaControllerTest, ActiveController_PreviousTrack) {
462 test::MockMediaSession media_session;
463 media_session.SetIsControllable(true);
464
465 EXPECT_EQ(0, media_session.prev_track_count());
466
467 {
468 test::MockMediaSessionMojoObserver observer(media_session);
469 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
470 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
471 EXPECT_EQ(0, media_session.prev_track_count());
472 }
473
474 controller()->PreviousTrack();
475 controller().FlushForTesting();
476
477 EXPECT_EQ(1, media_session.prev_track_count());
478 }
479
TEST_F(MediaControllerTest,ActiveController_NextTrack)480 TEST_F(MediaControllerTest, ActiveController_NextTrack) {
481 test::MockMediaSession media_session;
482 media_session.SetIsControllable(true);
483
484 EXPECT_EQ(0, media_session.next_track_count());
485
486 {
487 test::MockMediaSessionMojoObserver observer(media_session);
488 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
489 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
490 EXPECT_EQ(0, media_session.next_track_count());
491 }
492
493 controller()->NextTrack();
494 controller().FlushForTesting();
495
496 EXPECT_EQ(1, media_session.next_track_count());
497 }
498
TEST_F(MediaControllerTest,ActiveController_Seek)499 TEST_F(MediaControllerTest, ActiveController_Seek) {
500 test::MockMediaSession media_session;
501 media_session.SetIsControllable(true);
502
503 EXPECT_EQ(0, media_session.seek_count());
504
505 {
506 test::MockMediaSessionMojoObserver observer(media_session);
507 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
508 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
509 EXPECT_EQ(0, media_session.seek_count());
510 }
511
512 controller()->Seek(
513 base::TimeDelta::FromSeconds(mojom::kDefaultSeekTimeSeconds));
514 controller().FlushForTesting();
515
516 EXPECT_EQ(1, media_session.seek_count());
517 }
518
TEST_F(MediaControllerTest,ActiveController_SeekTo)519 TEST_F(MediaControllerTest, ActiveController_SeekTo) {
520 test::MockMediaSession media_session;
521 media_session.SetIsControllable(true);
522
523 EXPECT_EQ(0, media_session.seek_to_count());
524
525 {
526 test::MockMediaSessionMojoObserver observer(media_session);
527 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
528 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
529
530 EXPECT_EQ(0, media_session.seek_to_count());
531 }
532
533 controller()->SeekTo(
534 base::TimeDelta::FromSeconds(mojom::kDefaultSeekTimeSeconds));
535 controller().FlushForTesting();
536
537 EXPECT_EQ(1, media_session.seek_to_count());
538 }
539
TEST_F(MediaControllerTest,ActiveController_ScrubTo)540 TEST_F(MediaControllerTest, ActiveController_ScrubTo) {
541 test::MockMediaSession media_session;
542 media_session.SetIsControllable(true);
543
544 EXPECT_FALSE(media_session.is_scrubbing());
545 EXPECT_EQ(0, media_session.seek_to_count());
546
547 {
548 test::MockMediaSessionMojoObserver observer(media_session);
549 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
550 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
551
552 EXPECT_FALSE(media_session.is_scrubbing());
553 EXPECT_EQ(0, media_session.seek_to_count());
554 }
555
556 controller()->ScrubTo(
557 base::TimeDelta::FromSeconds(mojom::kDefaultSeekTimeSeconds));
558 controller().FlushForTesting();
559
560 EXPECT_TRUE(media_session.is_scrubbing());
561 EXPECT_EQ(0, media_session.seek_to_count());
562
563 controller()->ScrubTo(
564 base::TimeDelta::FromSeconds(mojom::kDefaultSeekTimeSeconds));
565 controller().FlushForTesting();
566
567 EXPECT_TRUE(media_session.is_scrubbing());
568 EXPECT_EQ(0, media_session.seek_to_count());
569
570 controller()->SeekTo(
571 base::TimeDelta::FromSeconds(mojom::kDefaultSeekTimeSeconds));
572 controller().FlushForTesting();
573
574 EXPECT_FALSE(media_session.is_scrubbing());
575 EXPECT_EQ(1, media_session.seek_to_count());
576 }
577
TEST_F(MediaControllerTest,ActiveController_Metadata_Observer_Abandoned)578 TEST_F(MediaControllerTest, ActiveController_Metadata_Observer_Abandoned) {
579 MediaMetadata metadata;
580 metadata.title = base::ASCIIToUTF16("title");
581 metadata.artist = base::ASCIIToUTF16("artist");
582 metadata.album = base::ASCIIToUTF16("album");
583
584 test::MockMediaSession media_session;
585 media_session.SetIsControllable(true);
586
587 base::Optional<MediaMetadata> test_metadata(metadata);
588
589 {
590 test::MockMediaSessionMojoObserver observer(media_session);
591 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
592 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
593 }
594
595 media_session.SimulateMetadataChanged(test_metadata);
596 media_session.AbandonAudioFocusFromClient();
597
598 {
599 test::TestMediaControllerObserver observer(controller());
600 observer.WaitForEmptyMetadata();
601 }
602 }
603
TEST_F(MediaControllerTest,ActiveController_Metadata_Observer_Empty)604 TEST_F(MediaControllerTest, ActiveController_Metadata_Observer_Empty) {
605 test::MockMediaSession media_session;
606 media_session.SetIsControllable(true);
607
608 base::Optional<MediaMetadata> test_metadata;
609
610 {
611 test::MockMediaSessionMojoObserver observer(media_session);
612 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
613 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
614 }
615
616 {
617 test::TestMediaControllerObserver observer(controller());
618 media_session.SimulateMetadataChanged(test_metadata);
619 observer.WaitForEmptyMetadata();
620 }
621 }
622
TEST_F(MediaControllerTest,ActiveController_Metadata_Observer_WithInfo)623 TEST_F(MediaControllerTest, ActiveController_Metadata_Observer_WithInfo) {
624 MediaMetadata metadata;
625 metadata.title = base::ASCIIToUTF16("title");
626 metadata.artist = base::ASCIIToUTF16("artist");
627 metadata.album = base::ASCIIToUTF16("album");
628
629 test::MockMediaSession media_session;
630 media_session.SetIsControllable(true);
631
632 base::Optional<MediaMetadata> test_metadata(metadata);
633
634 {
635 test::MockMediaSessionMojoObserver observer(media_session);
636 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
637 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
638 }
639
640 {
641 test::TestMediaControllerObserver observer(controller());
642 media_session.SimulateMetadataChanged(test_metadata);
643 observer.WaitForExpectedMetadata(metadata);
644 }
645 }
646
TEST_F(MediaControllerTest,ActiveController_Metadata_AddObserver_Empty)647 TEST_F(MediaControllerTest, ActiveController_Metadata_AddObserver_Empty) {
648 test::MockMediaSession media_session;
649 media_session.SetIsControllable(true);
650
651 base::Optional<MediaMetadata> test_metadata;
652
653 {
654 test::MockMediaSessionMojoObserver observer(media_session);
655 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
656 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
657 }
658
659 media_session.SimulateMetadataChanged(test_metadata);
660
661 {
662 test::TestMediaControllerObserver observer(controller());
663 observer.WaitForEmptyMetadata();
664 }
665 }
666
TEST_F(MediaControllerTest,ActiveController_Metadata_AddObserver_WithInfo)667 TEST_F(MediaControllerTest, ActiveController_Metadata_AddObserver_WithInfo) {
668 MediaMetadata metadata;
669 metadata.title = base::ASCIIToUTF16("title");
670 metadata.artist = base::ASCIIToUTF16("artist");
671 metadata.album = base::ASCIIToUTF16("album");
672
673 test::MockMediaSession media_session;
674 media_session.SetIsControllable(true);
675
676 base::Optional<MediaMetadata> test_metadata(metadata);
677
678 {
679 test::MockMediaSessionMojoObserver observer(media_session);
680 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
681 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
682 }
683
684 media_session.SimulateMetadataChanged(test_metadata);
685
686 {
687 test::TestMediaControllerObserver observer(controller());
688 observer.WaitForExpectedMetadata(metadata);
689 }
690 }
691
TEST_F(MediaControllerTest,ActiveController_Stop)692 TEST_F(MediaControllerTest, ActiveController_Stop) {
693 test::MockMediaSession media_session;
694 media_session.SetIsControllable(true);
695
696 {
697 test::MockMediaSessionMojoObserver observer(media_session);
698 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
699 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
700 }
701
702 {
703 test::MockMediaSessionMojoObserver observer(media_session);
704 controller()->Stop();
705 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kInactive);
706 }
707 }
708
TEST_F(MediaControllerTest,BoundController_Routing)709 TEST_F(MediaControllerTest, BoundController_Routing) {
710 test::MockMediaSession media_session_1;
711 test::MockMediaSession media_session_2;
712
713 media_session_1.SetIsControllable(true);
714 media_session_2.SetIsControllable(true);
715
716 {
717 test::MockMediaSessionMojoObserver observer(media_session_1);
718 RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
719 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
720 }
721
722 mojo::Remote<mojom::MediaController> controller;
723 manager()->CreateMediaControllerForSession(
724 controller.BindNewPipeAndPassReceiver(), media_session_1.request_id());
725 manager().FlushForTesting();
726
727 EXPECT_EQ(0, media_session_1.next_track_count());
728
729 controller->NextTrack();
730 controller.FlushForTesting();
731
732 EXPECT_EQ(1, media_session_1.next_track_count());
733
734 {
735 test::MockMediaSessionMojoObserver observer(media_session_2);
736 RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGain);
737 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
738 }
739
740 EXPECT_EQ(1, media_session_1.next_track_count());
741 EXPECT_EQ(0, media_session_2.next_track_count());
742
743 controller->NextTrack();
744 controller.FlushForTesting();
745
746 EXPECT_EQ(2, media_session_1.next_track_count());
747 EXPECT_EQ(0, media_session_2.next_track_count());
748 }
749
TEST_F(MediaControllerTest,BoundController_BadRequestId)750 TEST_F(MediaControllerTest, BoundController_BadRequestId) {
751 test::MockMediaSession media_session;
752 media_session.SetIsControllable(true);
753
754 {
755 test::MockMediaSessionMojoObserver observer(media_session);
756 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
757 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
758 }
759
760 mojo::Remote<mojom::MediaController> controller;
761 manager()->CreateMediaControllerForSession(
762 controller.BindNewPipeAndPassReceiver(),
763 base::UnguessableToken::Create());
764 manager().FlushForTesting();
765
766 EXPECT_EQ(0, media_session.next_track_count());
767
768 controller->NextTrack();
769 controller.FlushForTesting();
770
771 EXPECT_EQ(0, media_session.next_track_count());
772 }
773
TEST_F(MediaControllerTest,BoundController_DropOnAbandon)774 TEST_F(MediaControllerTest, BoundController_DropOnAbandon) {
775 test::MockMediaSession media_session;
776 media_session.SetIsControllable(true);
777
778 {
779 test::MockMediaSessionMojoObserver observer(media_session);
780 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
781 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
782 }
783
784 mojo::Remote<mojom::MediaController> controller;
785 manager()->CreateMediaControllerForSession(
786 controller.BindNewPipeAndPassReceiver(), media_session.request_id());
787 manager().FlushForTesting();
788
789 EXPECT_EQ(0, media_session.next_track_count());
790
791 controller->NextTrack();
792 controller.FlushForTesting();
793
794 EXPECT_EQ(1, media_session.next_track_count());
795
796 media_session.AbandonAudioFocusFromClient();
797
798 EXPECT_EQ(1, media_session.next_track_count());
799
800 controller->NextTrack();
801 controller.FlushForTesting();
802
803 EXPECT_EQ(1, media_session.next_track_count());
804 }
805
TEST_F(MediaControllerTest,ActiveController_Actions_AddObserver_Empty)806 TEST_F(MediaControllerTest, ActiveController_Actions_AddObserver_Empty) {
807 test::MockMediaSession media_session;
808 media_session.SetIsControllable(true);
809
810 {
811 test::MockMediaSessionMojoObserver observer(media_session);
812 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
813 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
814 }
815
816 {
817 test::TestMediaControllerObserver observer(controller());
818 observer.WaitForEmptyActions();
819 }
820 }
821
TEST_F(MediaControllerTest,ActiveController_Actions_AddObserver_WithInfo)822 TEST_F(MediaControllerTest, ActiveController_Actions_AddObserver_WithInfo) {
823 test::MockMediaSession media_session;
824 media_session.SetIsControllable(true);
825
826 {
827 test::MockMediaSessionMojoObserver observer(media_session);
828 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
829 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
830 }
831
832 media_session.EnableAction(mojom::MediaSessionAction::kPlay);
833
834 {
835 test::TestMediaControllerObserver observer(controller());
836
837 std::set<mojom::MediaSessionAction> expected_actions;
838 expected_actions.insert(mojom::MediaSessionAction::kPlay);
839 observer.WaitForExpectedActions(expected_actions);
840 }
841 }
842
TEST_F(MediaControllerTest,ActiveController_Actions_Observer_Empty)843 TEST_F(MediaControllerTest, ActiveController_Actions_Observer_Empty) {
844 test::MockMediaSession media_session;
845 media_session.EnableAction(mojom::MediaSessionAction::kPlay);
846 media_session.SetIsControllable(true);
847
848 {
849 test::MockMediaSessionMojoObserver observer(media_session);
850 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
851 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
852 }
853
854 {
855 test::TestMediaControllerObserver observer(controller());
856 media_session.DisableAction(mojom::MediaSessionAction::kPlay);
857 observer.WaitForEmptyActions();
858 }
859 }
860
TEST_F(MediaControllerTest,ActiveController_Actions_Observer_WithInfo)861 TEST_F(MediaControllerTest, ActiveController_Actions_Observer_WithInfo) {
862 test::MockMediaSession media_session;
863 media_session.SetIsControllable(true);
864
865 {
866 test::MockMediaSessionMojoObserver observer(media_session);
867 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
868 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
869 }
870
871 {
872 test::TestMediaControllerObserver observer(controller());
873 media_session.EnableAction(mojom::MediaSessionAction::kPlay);
874
875 std::set<mojom::MediaSessionAction> expected_actions;
876 expected_actions.insert(mojom::MediaSessionAction::kPlay);
877 observer.WaitForExpectedActions(expected_actions);
878 }
879 }
880
TEST_F(MediaControllerTest,ActiveController_Actions_Observer_Abandoned)881 TEST_F(MediaControllerTest, ActiveController_Actions_Observer_Abandoned) {
882 test::MockMediaSession media_session;
883 media_session.EnableAction(mojom::MediaSessionAction::kPlay);
884 media_session.SetIsControllable(true);
885
886 {
887 test::MockMediaSessionMojoObserver observer(media_session);
888 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
889 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
890 }
891
892 media_session.AbandonAudioFocusFromClient();
893
894 {
895 test::TestMediaControllerObserver observer(controller());
896 observer.WaitForEmptyActions();
897 }
898 }
899
TEST_F(MediaControllerTest,ActiveController_Position_Observer_Empty)900 TEST_F(MediaControllerTest, ActiveController_Position_Observer_Empty) {
901 test::MockMediaSession media_session;
902 media_session.SetIsControllable(true);
903
904 base::Optional<MediaPosition> test_position;
905
906 {
907 test::MockMediaSessionMojoObserver observer(media_session);
908 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
909 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
910 }
911
912 {
913 test::TestMediaControllerObserver observer(controller());
914 media_session.SimulatePositionChanged(test_position);
915 observer.WaitForEmptyPosition();
916 }
917 }
918
TEST_F(MediaControllerTest,ActiveController_Position_Observer_WithInfo)919 TEST_F(MediaControllerTest, ActiveController_Position_Observer_WithInfo) {
920 MediaPosition position(1 /* playback_rate */,
921 base::TimeDelta::FromSeconds(600) /* duration */,
922 base::TimeDelta::FromSeconds(300) /* position */);
923
924 test::MockMediaSession media_session;
925 media_session.SetIsControllable(true);
926
927 base::Optional<MediaPosition> test_position(position);
928
929 {
930 test::MockMediaSessionMojoObserver observer(media_session);
931 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
932 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
933 }
934
935 {
936 test::TestMediaControllerObserver observer(controller());
937 media_session.SimulatePositionChanged(test_position);
938 observer.WaitForNonEmptyPosition();
939 }
940 }
941
TEST_F(MediaControllerTest,ActiveController_Position_AddObserver_Empty)942 TEST_F(MediaControllerTest, ActiveController_Position_AddObserver_Empty) {
943 test::MockMediaSession media_session;
944 media_session.SetIsControllable(true);
945
946 base::Optional<MediaPosition> test_position;
947
948 {
949 test::MockMediaSessionMojoObserver observer(media_session);
950 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
951 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
952 }
953
954 media_session.SimulatePositionChanged(test_position);
955
956 {
957 test::TestMediaControllerObserver observer(controller());
958 observer.WaitForEmptyPosition();
959 }
960 }
961
TEST_F(MediaControllerTest,ActiveController_Position_AddObserver_WithInfo)962 TEST_F(MediaControllerTest, ActiveController_Position_AddObserver_WithInfo) {
963 MediaPosition position(1 /* playback_rate */,
964 base::TimeDelta::FromSeconds(600) /* duration */,
965 base::TimeDelta::FromSeconds(300) /* position */);
966
967 test::MockMediaSession media_session;
968 media_session.SetIsControllable(true);
969
970 base::Optional<MediaPosition> test_position(position);
971
972 {
973 test::MockMediaSessionMojoObserver observer(media_session);
974 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
975 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
976 }
977
978 media_session.SimulatePositionChanged(test_position);
979
980 {
981 test::TestMediaControllerObserver observer(controller());
982 observer.WaitForNonEmptyPosition();
983 }
984 }
985
TEST_F(MediaControllerTest,ActiveController_Position_Observer_Abandoned)986 TEST_F(MediaControllerTest, ActiveController_Position_Observer_Abandoned) {
987 MediaPosition position(1 /* playback_rate */,
988 base::TimeDelta::FromSeconds(600) /* duration */,
989 base::TimeDelta::FromSeconds(300) /* position */);
990
991 test::MockMediaSession media_session;
992 media_session.SetIsControllable(true);
993
994 base::Optional<MediaPosition> test_position(position);
995
996 {
997 test::MockMediaSessionMojoObserver observer(media_session);
998 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
999 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1000 }
1001
1002 media_session.SimulatePositionChanged(test_position);
1003 media_session.AbandonAudioFocusFromClient();
1004
1005 {
1006 test::TestMediaControllerObserver observer(controller());
1007 observer.WaitForEmptyPosition();
1008 }
1009 }
1010
TEST_F(MediaControllerTest,ActiveController_Observer_Abandoned)1011 TEST_F(MediaControllerTest, ActiveController_Observer_Abandoned) {
1012 test::MockMediaSession media_session;
1013 media_session.SetIsControllable(true);
1014
1015 {
1016 test::MockMediaSessionMojoObserver observer(media_session);
1017 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
1018 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1019 }
1020
1021 {
1022 test::TestMediaControllerObserver observer(controller());
1023 media_session.AbandonAudioFocusFromClient();
1024
1025 // We should see empty info, metadata, actions, and position flushed since
1026 // the active controller is no longer bound to a media session.
1027 observer.WaitForEmptyInfo();
1028 observer.WaitForEmptyMetadata();
1029 observer.WaitForEmptyActions();
1030 observer.WaitForEmptyPosition();
1031 }
1032 }
1033
TEST_F(MediaControllerTest,ActiveController_AddObserver_Abandoned)1034 TEST_F(MediaControllerTest, ActiveController_AddObserver_Abandoned) {
1035 test::MockMediaSession media_session;
1036 media_session.SetIsControllable(true);
1037
1038 {
1039 test::MockMediaSessionMojoObserver observer(media_session);
1040 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
1041 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1042 }
1043
1044 media_session.AbandonAudioFocusFromClient();
1045
1046 {
1047 test::TestMediaControllerObserver observer(controller());
1048
1049 // We should see empty info, metadata, actions, and position since the
1050 // active controller is no longer bound to a media session.
1051 observer.WaitForEmptyInfo();
1052 observer.WaitForEmptyMetadata();
1053 observer.WaitForEmptyActions();
1054 observer.WaitForEmptyPosition();
1055 }
1056 }
1057
TEST_F(MediaControllerTest,ClearImageObserverOnError)1058 TEST_F(MediaControllerTest, ClearImageObserverOnError) {
1059 MediaController controller;
1060
1061 mojo::Remote<mojom::MediaController> controller_remote;
1062 controller.BindToInterface(controller_remote.BindNewPipeAndPassReceiver());
1063 EXPECT_EQ(0u, GetImageObserverCount(controller));
1064
1065 {
1066 test::TestMediaControllerImageObserver observer(controller_remote, 0, 0);
1067 EXPECT_EQ(1u, GetImageObserverCount(controller));
1068 }
1069
1070 EXPECT_EQ(1u, GetImageObserverCount(controller));
1071
1072 base::RunLoop().RunUntilIdle();
1073
1074 EXPECT_EQ(0u, GetImageObserverCount(controller));
1075 }
1076
TEST_F(MediaControllerTest,ActiveController_SimulateImagesChanged)1077 TEST_F(MediaControllerTest, ActiveController_SimulateImagesChanged) {
1078 test::MockMediaSession media_session;
1079 media_session.SetIsControllable(true);
1080
1081 {
1082 test::MockMediaSessionMojoObserver observer(media_session);
1083 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
1084 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1085 }
1086
1087 std::vector<MediaImage> images;
1088 MediaImage image;
1089 image.src = GURL("https://www.google.com");
1090 images.push_back(image);
1091
1092 {
1093 test::TestMediaControllerImageObserver observer(controller(), 0, 0);
1094
1095 // By default, the image is empty but no notification should be received.
1096 EXPECT_TRUE(media_session.last_image_src().is_empty());
1097
1098 // Check that we receive the correct image and that it was requested from
1099 // |media_session| by the controller.
1100 media_session.SetImagesOfType(mojom::MediaSessionImageType::kArtwork,
1101 images);
1102 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1103 false);
1104 EXPECT_EQ(image.src, media_session.last_image_src());
1105
1106 // Check that we flush the observer with an empty image. Since the image is
1107 // empty the last downloaded image by |media_session| should still be the
1108 // previous image.
1109 media_session.SetImagesOfType(mojom::MediaSessionImageType::kArtwork,
1110 std::vector<MediaImage>());
1111 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1112 true);
1113 EXPECT_EQ(image.src, media_session.last_image_src());
1114 }
1115 }
1116
TEST_F(MediaControllerTest,ActiveController_SimulateImagesChanged_ToggleControllable)1117 TEST_F(MediaControllerTest,
1118 ActiveController_SimulateImagesChanged_ToggleControllable) {
1119 test::MockMediaSession media_session;
1120 media_session.SetIsControllable(true);
1121
1122 {
1123 test::MockMediaSessionMojoObserver observer(media_session);
1124 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
1125 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1126 }
1127
1128 std::vector<MediaImage> images;
1129 MediaImage image;
1130 image.src = GURL("https://www.google.com");
1131 images.push_back(image);
1132 media_session.SetImagesOfType(mojom::MediaSessionImageType::kArtwork, images);
1133
1134 {
1135 test::TestMediaControllerImageObserver observer(controller(), 0, 0);
1136 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1137 false);
1138 EXPECT_EQ(image.src, media_session.last_image_src());
1139
1140 // When the |media_session| becomes uncontrollable it is unbound from the
1141 // media controller and we should flush the observer with an empty image.
1142 media_session.SetIsControllable(false);
1143 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1144 true);
1145
1146 // When the |media_session| becomes controllable again it will be bound to
1147 // the media controller and we should flush the observer with the current
1148 // images.
1149 media_session.SetIsControllable(true);
1150 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1151 false);
1152 EXPECT_EQ(image.src, media_session.last_image_src());
1153 }
1154 }
1155
TEST_F(MediaControllerTest,ActiveController_SimulateImagesChanged_TypeChanged)1156 TEST_F(MediaControllerTest,
1157 ActiveController_SimulateImagesChanged_TypeChanged) {
1158 test::MockMediaSession media_session;
1159 media_session.SetIsControllable(true);
1160
1161 {
1162 test::MockMediaSessionMojoObserver observer(media_session);
1163 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
1164 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1165 }
1166
1167 std::vector<MediaImage> images;
1168 MediaImage image;
1169 image.src = GURL("https://www.google.com");
1170 images.push_back(image);
1171 media_session.SetImagesOfType(mojom::MediaSessionImageType::kArtwork, images);
1172
1173 {
1174 test::TestMediaControllerImageObserver observer(controller(), 0, 0);
1175 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1176 false);
1177 EXPECT_EQ(image.src, media_session.last_image_src());
1178
1179 // If we clear all the images associated with the media session we should
1180 // flush all the observers.
1181 media_session.ClearAllImages();
1182 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1183 true);
1184 EXPECT_EQ(image.src, media_session.last_image_src());
1185 }
1186 }
1187
TEST_F(MediaControllerTest,ActiveController_SimulateImagesChanged_MinSizeCutoff)1188 TEST_F(MediaControllerTest,
1189 ActiveController_SimulateImagesChanged_MinSizeCutoff) {
1190 test::MockMediaSession media_session;
1191 media_session.SetIsControllable(true);
1192
1193 {
1194 test::MockMediaSessionMojoObserver observer(media_session);
1195 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
1196 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1197 }
1198
1199 std::vector<MediaImage> images;
1200 MediaImage image1;
1201 image1.src = GURL("https://www.google.com");
1202 image1.sizes.push_back(gfx::Size(1, 1));
1203
1204 media_session.SetImagesOfType(mojom::MediaSessionImageType::kArtwork,
1205 {image1});
1206
1207 {
1208 test::TestMediaControllerImageObserver observer(controller(), 5, 10);
1209
1210 // The observer requires an image that is at least 5px but the only image
1211 // we have is 1px so the observer will not be notified.
1212 EXPECT_TRUE(media_session.last_image_src().is_empty());
1213
1214 MediaImage image2;
1215 image2.src = GURL("https://www.example.com");
1216 image2.sizes.push_back(gfx::Size(10, 10));
1217
1218 // Update the media session with two images, one that is too small and one
1219 // that is the right size. We should receive the second image through the
1220 // observer.
1221 media_session.SetImagesOfType(mojom::MediaSessionImageType::kArtwork,
1222 {image1, image2});
1223 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1224 false);
1225 EXPECT_EQ(image2.src, media_session.last_image_src());
1226
1227 // Use the first set of images again.
1228 media_session.SetImagesOfType(mojom::MediaSessionImageType::kArtwork,
1229 {image1});
1230 // The observer requires as image that is at least 5px and should now be
1231 // notified that the image was cleared.
1232 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1233 true);
1234 }
1235 }
1236
TEST_F(MediaControllerTest,ActiveController_SimulateImagesChanged_DesiredSize)1237 TEST_F(MediaControllerTest,
1238 ActiveController_SimulateImagesChanged_DesiredSize) {
1239 test::MockMediaSession media_session;
1240 media_session.SetIsControllable(true);
1241
1242 {
1243 test::MockMediaSessionMojoObserver observer(media_session);
1244 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
1245 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1246 }
1247
1248 std::vector<MediaImage> images;
1249 MediaImage image1;
1250 image1.src = GURL("https://www.google.com");
1251 image1.sizes.push_back(gfx::Size(10, 10));
1252 images.push_back(image1);
1253
1254 MediaImage image2;
1255 image2.src = GURL("https://www.example.com");
1256 image2.sizes.push_back(gfx::Size(9, 9));
1257 images.push_back(image2);
1258
1259 media_session.SetImagesOfType(mojom::MediaSessionImageType::kArtwork, images);
1260
1261 {
1262 test::TestMediaControllerImageObserver observer(controller(), 5, 10);
1263
1264 // The media session has two images, but the first one is closer to the 10px
1265 // desired size that the observer has specified. Therefore, the observer
1266 // should receive that image.
1267 media_session.SetImagesOfType(mojom::MediaSessionImageType::kArtwork,
1268 images);
1269 observer.WaitForExpectedImageOfType(mojom::MediaSessionImageType::kArtwork,
1270 false);
1271 EXPECT_EQ(image1.src, media_session.last_image_src());
1272 }
1273 }
1274
TEST_F(MediaControllerTest,ActiveController_Observer_SessionChanged)1275 TEST_F(MediaControllerTest, ActiveController_Observer_SessionChanged) {
1276 test::MockMediaSession media_session_1;
1277 test::MockMediaSession media_session_2;
1278
1279 media_session_1.SetIsControllable(true);
1280 media_session_2.SetIsControllable(true);
1281
1282 {
1283 test::TestMediaControllerObserver observer(controller());
1284 observer.WaitForSession(base::nullopt);
1285 }
1286
1287 {
1288 test::MockMediaSessionMojoObserver observer(media_session_1);
1289 RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
1290 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1291 }
1292
1293 {
1294 test::TestMediaControllerObserver observer(controller());
1295 observer.WaitForSession(media_session_1.request_id());
1296 }
1297
1298 {
1299 test::TestMediaControllerObserver observer(controller());
1300 RequestAudioFocus(media_session_2, mojom::AudioFocusType::kGain);
1301 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1302 }
1303
1304 {
1305 test::TestMediaControllerObserver observer(controller());
1306 observer.WaitForSession(media_session_2.request_id());
1307 }
1308
1309 {
1310 test::TestMediaControllerObserver observer(controller());
1311 media_session_2.AbandonAudioFocusFromClient();
1312 observer.WaitForSession(media_session_1.request_id());
1313 }
1314
1315 {
1316 test::TestMediaControllerObserver observer(controller());
1317 media_session_1.SetIsControllable(false);
1318 observer.WaitForSession(base::nullopt);
1319 }
1320 }
1321
TEST_F(MediaControllerTest,BoundController_Observer_SessionChanged)1322 TEST_F(MediaControllerTest, BoundController_Observer_SessionChanged) {
1323 test::MockMediaSession media_session;
1324
1325 {
1326 test::MockMediaSessionMojoObserver observer(media_session);
1327 RequestAudioFocus(media_session, mojom::AudioFocusType::kGain);
1328 observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
1329 }
1330
1331 mojo::Remote<mojom::MediaController> controller;
1332 manager()->CreateMediaControllerForSession(
1333 controller.BindNewPipeAndPassReceiver(), media_session.request_id());
1334 manager().FlushForTesting();
1335
1336 {
1337 test::TestMediaControllerObserver observer(controller);
1338 observer.WaitForSession(media_session.request_id());
1339 }
1340 }
1341
TEST_F(MediaControllerTest,Manager_SuspendAllSessions)1342 TEST_F(MediaControllerTest, Manager_SuspendAllSessions) {
1343 test::MockMediaSession media_session_1;
1344 test::MockMediaSession media_session_2;
1345
1346 {
1347 test::MockMediaSessionMojoObserver observer(media_session_1);
1348 RequestAudioFocus(media_session_1, mojom::AudioFocusType::kGain);
1349 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
1350 }
1351
1352 {
1353 test::MockMediaSessionMojoObserver observer(media_session_2);
1354 RequestAudioFocus(media_session_2,
1355 mojom::AudioFocusType::kGainTransientMayDuck);
1356 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPlaying);
1357 }
1358
1359 manager()->SuspendAllSessions();
1360
1361 {
1362 test::MockMediaSessionMojoObserver observer(media_session_1);
1363 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
1364 }
1365
1366 {
1367 test::MockMediaSessionMojoObserver observer(media_session_2);
1368 observer.WaitForPlaybackState(mojom::MediaPlaybackState::kPaused);
1369 }
1370 }
1371
1372 } // namespace media_session
1373