Commit 84ba1114 authored by Noah Rose Ledesma's avatar Noah Rose Ledesma Committed by Commit Bot

Persist GMC audio device selection through same origin navigation

When an audio device is selected via the GMC UI that setting should
persist for all media on that origin in that sesion until another
selection is made.

Bug: 1122134
Change-Id: Icbdd58db3c0e2233804004065958dcd544d37c38
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2378450Reviewed-by: default avatarBecca Hughes <beccahughes@chromium.org>
Commit-Queue: Noah Rose Ledesma <noahrose@google.com>
Cr-Commit-Position: refs/heads/master@{#802064}
parent 5555c98b
...@@ -269,6 +269,13 @@ void MediaSessionImpl::DidFinishNavigation( ...@@ -269,6 +269,13 @@ void MediaSessionImpl::DidFinishNavigation(
return; return;
} }
auto new_origin = url::Origin::Create(navigation_handle->GetURL());
if (navigation_handle->IsInMainFrame() &&
!new_origin.IsSameOriginWith(origin_)) {
audio_device_id_for_origin_.reset();
origin_ = new_origin;
}
RenderFrameHost* rfh = navigation_handle->GetRenderFrameHost(); RenderFrameHost* rfh = navigation_handle->GetRenderFrameHost();
if (services_.count(rfh)) if (services_.count(rfh))
services_[rfh]->DidFinishNavigation(); services_[rfh]->DidFinishNavigation();
...@@ -351,6 +358,8 @@ bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer, ...@@ -351,6 +358,8 @@ bool MediaSessionImpl::AddPlayer(MediaSessionPlayerObserver* observer,
return AddPepperPlayer(observer, player_id); return AddPepperPlayer(observer, player_id);
observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier()); observer->OnSetVolumeMultiplier(player_id, GetVolumeMultiplier());
if (audio_device_id_for_origin_)
observer->OnSetAudioSinkId(player_id, audio_device_id_for_origin_.value());
AudioFocusType required_audio_focus_type; AudioFocusType required_audio_focus_type;
if (media_content_type == media::MediaContentType::Persistent) if (media_content_type == media::MediaContentType::Persistent)
...@@ -1079,6 +1088,8 @@ void MediaSessionImpl::ExitPictureInPicture() { ...@@ -1079,6 +1088,8 @@ void MediaSessionImpl::ExitPictureInPicture() {
} }
void MediaSessionImpl::SetAudioSinkId(const base::Optional<std::string>& id) { void MediaSessionImpl::SetAudioSinkId(const base::Optional<std::string>& id) {
audio_device_id_for_origin_ = id;
for (const auto& it : normal_players_) { for (const auto& it : normal_players_) {
it.first.observer->OnSetAudioSinkId( it.first.observer->OnSetAudioSinkId(
it.first.player_id, it.first.player_id,
...@@ -1366,6 +1377,11 @@ void MediaSessionImpl::OnPictureInPictureAvailabilityChanged() { ...@@ -1366,6 +1377,11 @@ void MediaSessionImpl::OnPictureInPictureAvailabilityChanged() {
} }
void MediaSessionImpl::OnAudioOutputSinkIdChanged() { void MediaSessionImpl::OnAudioOutputSinkIdChanged() {
if (audio_device_id_for_origin_ &&
audio_device_id_for_origin_ != GetSharedAudioOutputDeviceId()) {
audio_device_id_for_origin_.reset();
}
RebuildAndNotifyMediaSessionInfoChanged(); RebuildAndNotifyMediaSessionInfoChanged();
} }
......
...@@ -255,6 +255,10 @@ class MediaSessionImpl : public MediaSession, ...@@ -255,6 +255,10 @@ class MediaSessionImpl : public MediaSession,
// Routes the audio from this Media Session to the given output device. If // Routes the audio from this Media Session to the given output device. If
// |id| is null, we will route to the default output device. // |id| is null, we will route to the default output device.
// Players created after this setting has been set will also have their audio
// rerouted. This setting persists until cross-origin navigation occurs, the
// renderer reports an audio sink change to a device different from |id|, or
// this method is called again.
void SetAudioSinkId(const base::Optional<std::string>& id) override; void SetAudioSinkId(const base::Optional<std::string>& id) override;
// Downloads the bitmap version of a MediaImage at least |minimum_size_px| // Downloads the bitmap version of a MediaImage at least |minimum_size_px|
...@@ -452,6 +456,11 @@ class MediaSessionImpl : public MediaSession, ...@@ -452,6 +456,11 @@ class MediaSessionImpl : public MediaSession,
// True if the WebContents associated with this MediaSessionImpl is focused. // True if the WebContents associated with this MediaSessionImpl is focused.
bool focused_ = false; bool focused_ = false;
// Used to persist audio device selection between navigations on the same
// origin.
url::Origin origin_;
base::Optional<std::string> audio_device_id_for_origin_;
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
std::unique_ptr<MediaSessionAndroid> session_android_; std::unique_ptr<MediaSessionAndroid> session_android_;
#endif // defined(OS_ANDROID) #endif // defined(OS_ANDROID)
......
...@@ -2886,4 +2886,52 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest, ...@@ -2886,4 +2886,52 @@ IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
} }
} }
IN_PROC_BROWSER_TEST_F(MediaSessionImplBrowserTest,
AudioDeviceSettingPersists) {
// When an audio output device has been set: in addition to players switching
// to that audio device, players created later on the same origin in the same
// session should also use that device.
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
auto player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
int player_1 = player_observer->StartNewPlayer();
AddPlayer(player_observer.get(), player_1,
media::MediaContentType::Persistent);
UISetAudioSink("speaker1");
EXPECT_EQ(player_observer->GetAudioOutputSinkId(player_1), "speaker1");
// When a second player has been added on the same page, it should use the
// audio device previously set.
int player_2 = player_observer->StartNewPlayer();
AddPlayer(player_observer.get(), player_2,
media::MediaContentType::Persistent);
EXPECT_EQ(player_observer->GetAudioOutputSinkId(player_2), "speaker1");
// Clear the players and navigate to a new page on the same origin.
RemovePlayers(player_observer.get());
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("a.com", "/title2.html")));
player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
// After navigating to another page on the same origin, newly created players
// should use the previously set device.
player_1 = player_observer->StartNewPlayer();
AddPlayer(player_observer.get(), player_1,
media::MediaContentType::Persistent);
EXPECT_EQ(player_observer->GetAudioOutputSinkId(player_1), "speaker1");
// Clear the players and navigate to a new page on a different origin
RemovePlayers(player_observer.get());
EXPECT_TRUE(NavigateToURL(
shell(), embedded_test_server()->GetURL("b.com", "/title1.html")));
player_observer = std::make_unique<MockMediaSessionPlayerObserver>();
// After navigating to another page on a different origin, newly created
// players should not use the previously set device.
player_1 = player_observer->StartNewPlayer();
AddPlayer(player_observer.get(), player_1,
media::MediaContentType::Persistent);
EXPECT_NE(player_observer->GetAudioOutputSinkId(player_1), "speaker1");
}
} // namespace content } // namespace content
...@@ -76,7 +76,7 @@ void MockMediaSessionPlayerObserver::OnSetAudioSinkId( ...@@ -76,7 +76,7 @@ void MockMediaSessionPlayerObserver::OnSetAudioSinkId(
int player_id, int player_id,
const std::string& raw_device_id) { const std::string& raw_device_id) {
EXPECT_GE(player_id, 0); EXPECT_GE(player_id, 0);
EXPECT_EQ(players_.size(), 1u); EXPECT_GT(players_.size(), static_cast<size_t>(player_id));
++received_set_audio_sink_id_calls_; ++received_set_audio_sink_id_calls_;
players_[player_id].audio_sink_id_ = raw_device_id; players_[player_id].audio_sink_id_ = raw_device_id;
......
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