Commit 1112acc3 authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

Media Controller: Add support for previous and next track

Add support for Previous/NextTrack to MediaController
and the underlying MediaSession. This will be mapped
to the previous and next track media keys on CrOS.

BUG=893296

Change-Id: I582cd70a04c24af69c80ca891a281311b4d05434
Reviewed-on: https://chromium-review.googlesource.com/c/1287268Reviewed-by: default avatarJochen Eisinger <jochen@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#603528}
parent 754c97a7
......@@ -44,6 +44,8 @@ class MockMediaSession : public content::MediaSession {
MOCK_METHOD1(RemoveObserver, void(content::MediaSessionObserver*));
MOCK_METHOD1(GetMediaSessionInfo, void(GetMediaSessionInfoCallback));
MOCK_METHOD1(GetDebugInfo, void(GetDebugInfoCallback));
MOCK_METHOD0(PreviousTrack, void());
MOCK_METHOD0(NextTrack, void());
private:
DISALLOW_COPY_AND_ASSIGN(MockMediaSession);
......
......@@ -755,6 +755,14 @@ void MediaSessionImpl::FinishSystemAudioFocusRequest(
}
}
void MediaSessionImpl::PreviousTrack() {
DidReceiveAction(blink::mojom::MediaSessionAction::PREVIOUS_TRACK);
}
void MediaSessionImpl::NextTrack() {
DidReceiveAction(blink::mojom::MediaSessionAction::NEXT_TRACK);
}
void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() {
if (audio_focus_state_ == State::INACTIVE || !normal_players_.empty() ||
!pepper_players_.empty() || !one_shot_players_.empty()) {
......
......@@ -227,6 +227,12 @@ class MediaSessionImpl : public MediaSession,
media_session::mojom::AudioFocusType type,
bool result);
// Skip to the previous track.
CONTENT_EXPORT void PreviousTrack() override;
// Skip to the next track.
CONTENT_EXPORT void NextTrack() override;
private:
friend class content::WebContentsUserData<MediaSessionImpl>;
friend class ::MediaSessionImplBrowserTest;
......
......@@ -413,4 +413,45 @@ TEST_F(MediaSessionImplServiceRoutingTest,
->DidReceiveAction(blink::mojom::MediaSessionAction::PAUSE);
}
TEST_F(MediaSessionImplServiceRoutingTest,
TestPreviousTrackBehaviorWhenMainFrameIsRouted) {
base::RunLoop run_loop;
StartPlayerForFrame(main_frame_);
StartPlayerForFrame(sub_frame_);
CreateServiceForFrame(main_frame_);
EXPECT_CALL(
*GetClientForFrame(main_frame_),
DidReceiveAction(blink::mojom::MediaSessionAction::PREVIOUS_TRACK))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
services_[main_frame_]->EnableAction(
blink::mojom::MediaSessionAction::PREVIOUS_TRACK);
MediaSessionImpl::Get(contents())->PreviousTrack();
run_loop.Run();
}
TEST_F(MediaSessionImplServiceRoutingTest,
TestNextTrackBehaviorWhenMainFrameIsRouted) {
base::RunLoop run_loop;
StartPlayerForFrame(main_frame_);
StartPlayerForFrame(sub_frame_);
CreateServiceForFrame(main_frame_);
EXPECT_CALL(*GetClientForFrame(main_frame_),
DidReceiveAction(blink::mojom::MediaSessionAction::NEXT_TRACK))
.WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
services_[main_frame_]->EnableAction(
blink::mojom::MediaSessionAction::NEXT_TRACK);
MediaSessionImpl::Get(contents())->NextTrack();
run_loop.Run();
}
} // namespace content
......@@ -85,6 +85,14 @@ class MediaSession : public media_session::mojom::MediaSession {
void AddObserver(
media_session::mojom::MediaSessionObserverPtr observer) override = 0;
// Skip to the previous track. If there is no previous track then this will be
// a no-op.
void PreviousTrack() override = 0;
// Skip to the next track. If there is no next track then this will be a
// no-op.
void NextTrack() override = 0;
protected:
MediaSession() = default;
......
......@@ -63,6 +63,20 @@ void MediaController::MediaSessionInfoChanged(mojom::MediaSessionInfoPtr info) {
session_info_ = std::move(info);
}
void MediaController::PreviousTrack() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (session_)
session_->PreviousTrack();
}
void MediaController::NextTrack() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (session_)
session_->NextTrack();
}
void MediaController::SetMediaSession(mojom::MediaSession* session) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
session_ = session;
......
......@@ -31,6 +31,8 @@ class MediaController : public mojom::MediaController,
void Resume() override;
void ToggleSuspendResume() override;
void AddObserver(mojom::MediaSessionObserverPtr) override;
void PreviousTrack() override;
void NextTrack() override;
// mojom::MediaSessionObserver overrides.
void MediaSessionInfoChanged(mojom::MediaSessionInfoPtr) override;
......
......@@ -276,4 +276,38 @@ TEST_F(MediaControllerTest, ActiveController_Observer_StateTransition) {
}
}
TEST_F(MediaControllerTest, ActiveController_PreviousTrack) {
test::MockMediaSession media_session;
EXPECT_EQ(0, media_session.prev_track_count());
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
EXPECT_EQ(0, media_session.prev_track_count());
}
controller()->PreviousTrack();
controller().FlushForTesting();
EXPECT_EQ(1, media_session.prev_track_count());
}
TEST_F(MediaControllerTest, ActiveController_NextTrack) {
test::MockMediaSession media_session;
EXPECT_EQ(0, media_session.next_track_count());
{
test::MockMediaSessionMojoObserver observer(media_session);
RequestAudioFocus(media_session);
observer.WaitForState(mojom::MediaSessionInfo::SessionState::kActive);
EXPECT_EQ(0, media_session.next_track_count());
}
controller()->NextTrack();
controller().FlushForTesting();
EXPECT_EQ(1, media_session.next_track_count());
}
} // namespace media_session
......@@ -102,6 +102,14 @@ void MockMediaSession::GetDebugInfo(GetDebugInfoCallback callback) {
std::move(callback).Run(std::move(debug_info));
}
void MockMediaSession::PreviousTrack() {
prev_track_count_++;
}
void MockMediaSession::NextTrack() {
next_track_count_++;
}
void MockMediaSession::Stop() {
SetState(mojom::MediaSessionInfo::SessionState::kInactive);
}
......
......@@ -63,6 +63,8 @@ class MockMediaSession : public mojom::MediaSession {
void GetMediaSessionInfo(GetMediaSessionInfoCallback) override;
void AddObserver(mojom::MediaSessionObserverPtr) override;
void GetDebugInfo(GetDebugInfoCallback) override;
void PreviousTrack() override;
void NextTrack() override;
void Stop();
......@@ -80,6 +82,9 @@ class MockMediaSession : public mojom::MediaSession {
}
void FlushForTesting();
int prev_track_count() const { return prev_track_count_; }
int next_track_count() const { return next_track_count_; }
private:
void SetState(mojom::MediaSessionInfo::SessionState);
void NotifyObservers();
......@@ -90,6 +95,9 @@ class MockMediaSession : public mojom::MediaSession {
const bool force_duck_ = false;
bool is_ducking_ = false;
int prev_track_count_ = 0;
int next_track_count_ = 0;
mojom::MediaSessionInfo::SessionState state_ =
mojom::MediaSessionInfo::SessionState::kInactive;
......
......@@ -26,6 +26,8 @@ class COMPONENT_EXPORT(MEDIA_SESSION_TEST_SUPPORT_CPP) TestMediaController
void Resume() override {}
void ToggleSuspendResume() override;
void AddObserver(mojom::MediaSessionObserverPtr) override {}
void PreviousTrack() override {}
void NextTrack() override {}
int toggle_suspend_resume_count() const {
return toggle_suspend_resume_count_;
......
......@@ -24,4 +24,10 @@ interface MediaController {
// If the active session changes then observers do not need to be readded.
// Adding the observer will update the observer with the latest state.
AddObserver(MediaSessionObserver observer);
// Skip to the previous track.
PreviousTrack();
// Skip to the next track.
NextTrack();
};
......@@ -65,7 +65,7 @@ interface MediaSessionObserver {
// WebContents or ARC app.
// TODO(https://crbug.com/875004): migrate media session from content/public
// to mojo.
// Next Method ID: 6
// Next Method ID: 9
interface MediaSession {
[Extensible]
enum SuspendType {
......@@ -100,4 +100,10 @@ interface MediaSession {
Resume@5(SuspendType suspend_type);
AddObserver@6(MediaSessionObserver observer);
// Skip to the previous track.
PreviousTrack@7();
// Skip to the next track.
NextTrack@8();
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment