Commit 2f7072ff authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

[Media Session] Switch content to using the service

Switch the content MediaSession code to using the audio
focus service on non-Android platforms.

BUG=875004

Change-Id: I8171a7351a7d64065564fe5f75937e1abaef8e7c
Reviewed-on: https://chromium-review.googlesource.com/c/1207657Reviewed-by: default avatarFredrik Hubinette <hubbe@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596456}
parent 68b5a64d
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/task/post_task.h" #include "base/task/post_task.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/browser/media/session/audio_focus_manager.h"
#include "content/browser/media/session/media_session_impl.h" #include "content/browser/media/session/media_session_impl.h"
#include "content/browser/renderer_host/media/media_stream_manager.h" #include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_context.h"
...@@ -30,10 +29,13 @@ ...@@ -30,10 +29,13 @@
#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui.h"
#include "content/public/common/service_manager_connection.h"
#include "media/base/audio_parameters.h" #include "media/base/audio_parameters.h"
#include "media/base/media_log_event.h" #include "media/base/media_log_event.h"
#include "media/filters/gpu_video_decoder.h" #include "media/filters/gpu_video_decoder.h"
#include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/media_session/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
#include "media/filters/decrypting_video_decoder.h" #include "media/filters/decrypting_video_decoder.h"
...@@ -719,33 +721,20 @@ void MediaInternals::SendVideoCaptureDeviceCapabilities() { ...@@ -719,33 +721,20 @@ void MediaInternals::SendVideoCaptureDeviceCapabilities() {
} }
void MediaInternals::SendAudioFocusState() { void MediaInternals::SendAudioFocusState() {
#if !defined(OS_ANDROID)
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!CanUpdate()) if (!CanUpdate())
return; return;
audio_focus_data_.Clear(); content::ServiceManagerConnection::GetForProcess()
->GetConnector()
auto& stack = AudioFocusManager::GetInstance()->audio_focus_stack_; ->BindInterface(media_session::mojom::kServiceName, &audio_focus_ptr_);
// We should go backwards through the stack so the top of the stack is always
// shown first in the list.
base::ListValue stack_data;
for (auto iter = stack.rbegin(); iter != stack.rend(); ++iter) {
base::DictionaryValue media_session_data;
media_session_data.SetKey(kAudioFocusIdKey, base::Value((*iter)->id()));
stack_data.GetList().push_back(std::move(media_session_data));
(*iter)->session()->GetDebugInfo(
base::BindOnce(&MediaInternals::DidGetAudioFocusDebugInfo,
base::Unretained(this), (*iter)->id()));
}
audio_focus_data_.SetKey(kAudioFocusSessionsKey, std::move(stack_data)); if (!audio_focus_ptr_.is_bound())
return;
if (stack.empty()) // Get the audio focus state from the media session service.
SendUpdate(SerializeUpdate(kAudioFocusFunction, &audio_focus_data_)); audio_focus_ptr_->GetFocusRequests(base::BindOnce(
#endif // !defined(OS_ANDROID) &MediaInternals::DidGetAudioFocusRequestList, base::Unretained(this)));
} }
void MediaInternals::UpdateVideoCaptureDeviceCapabilities( void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
...@@ -847,6 +836,43 @@ void MediaInternals::OnFocusLost( ...@@ -847,6 +836,43 @@ void MediaInternals::OnFocusLost(
base::Unretained(this))); base::Unretained(this)));
} }
void MediaInternals::DidGetAudioFocusRequestList(
std::vector<media_session::mojom::AudioFocusRequestStatePtr> stack) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!CanUpdate())
return;
content::ServiceManagerConnection::GetForProcess()
->GetConnector()
->BindInterface(media_session::mojom::kServiceName,
&audio_focus_debug_ptr_);
if (!audio_focus_debug_ptr_.is_bound())
return;
audio_focus_data_.Clear();
// We should go backwards through the stack so the top of the stack is
// always shown first in the list.
base::ListValue stack_data;
for (auto iter = stack.rbegin(); iter != stack.rend(); ++iter) {
int request_id = (*iter)->request_id;
base::DictionaryValue media_session_data;
media_session_data.SetKey(kAudioFocusIdKey, base::Value(request_id));
stack_data.GetList().push_back(std::move(media_session_data));
audio_focus_debug_ptr_->GetDebugInfoForRequest(
request_id, base::BindOnce(&MediaInternals::DidGetAudioFocusDebugInfo,
base::Unretained(this), request_id));
}
audio_focus_data_.SetKey(kAudioFocusSessionsKey, std::move(stack_data));
if (stack.empty())
SendUpdate(SerializeUpdate(kAudioFocusFunction, &audio_focus_data_));
}
void MediaInternals::DidGetAudioFocusDebugInfo( void MediaInternals::DidGetAudioFocusDebugInfo(
int id, int id,
media_session::mojom::MediaSessionDebugInfoPtr info) { media_session::mojom::MediaSessionDebugInfoPtr info) {
......
...@@ -126,7 +126,12 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory, ...@@ -126,7 +126,12 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
void OnFocusLost( void OnFocusLost(
media_session::mojom::MediaSessionInfoPtr media_session) override; media_session::mojom::MediaSessionInfoPtr media_session) override;
// Called when we receive audio focus debug info to display. // Called when we receive the list of audio focus requests to display.
void DidGetAudioFocusRequestList(
std::vector<media_session::mojom::AudioFocusRequestStatePtr>);
// Called when we receive audio focus debug info to display for a single
// audio focus request.
void DidGetAudioFocusDebugInfo( void DidGetAudioFocusDebugInfo(
int id, int id,
media_session::mojom::MediaSessionDebugInfoPtr info); media_session::mojom::MediaSessionDebugInfoPtr info);
...@@ -157,6 +162,10 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory, ...@@ -157,6 +162,10 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
int render_process_id, int render_process_id,
int render_frame_id); int render_frame_id);
// Holds a pointer to the media session service and it's debug interface.
media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
media_session::mojom::AudioFocusManagerDebugPtr audio_focus_debug_ptr_;
// Must only be accessed on the UI thread. // Must only be accessed on the UI thread.
std::vector<UpdateCallback> update_callbacks_; std::vector<UpdateCallback> update_callbacks_;
......
...@@ -12,14 +12,15 @@ ...@@ -12,14 +12,15 @@
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/test/scoped_command_line.h" #include "base/test/scoped_command_line.h"
#include "base/test/test_message_loop.h" #include "base/test/test_message_loop.h"
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/browser/media/session/audio_focus_manager.h"
#include "content/browser/media/session/media_session_impl.h" #include "content/browser/media/session/media_session_impl.h"
#include "content/public/test/test_browser_context.h" #include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h" #include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_service_manager_context.h"
#include "content/test/test_web_contents.h" #include "content/test/test_web_contents.h"
#include "media/base/audio_parameters.h" #include "media/base/audio_parameters.h"
#include "media/base/channel_layout.h" #include "media/base/channel_layout.h"
...@@ -40,8 +41,15 @@ const char kTestDeviceID[] = "test-device-id"; ...@@ -40,8 +41,15 @@ const char kTestDeviceID[] = "test-device-id";
// integer/string values. // integer/string values.
class MediaInternalsTestBase { class MediaInternalsTestBase {
public: public:
MediaInternalsTestBase() MediaInternalsTestBase() : media_internals_(nullptr) {
: media_internals_(content::MediaInternals::GetInstance()) {} scoped_command_line_.GetProcessCommandLine()->AppendSwitch(
media_session::switches::kEnableAudioFocus);
service_manager_context_ =
std::make_unique<content::TestServiceManagerContext>();
media_internals_ = content::MediaInternals::GetInstance();
}
virtual ~MediaInternalsTestBase() {} virtual ~MediaInternalsTestBase() {}
protected: protected:
...@@ -98,7 +106,14 @@ class MediaInternalsTestBase { ...@@ -98,7 +106,14 @@ class MediaInternalsTestBase {
const content::TestBrowserThreadBundle thread_bundle_; const content::TestBrowserThreadBundle thread_bundle_;
base::DictionaryValue update_data_; base::DictionaryValue update_data_;
content::MediaInternals* const media_internals_;
content::MediaInternals* media_internals() const { return media_internals_; }
private:
content::MediaInternals* media_internals_;
base::test::ScopedCommandLine scoped_command_line_;
std::unique_ptr<content::TestServiceManagerContext> service_manager_context_;
}; };
} // namespace } // namespace
...@@ -114,11 +129,11 @@ class MediaInternalsVideoCaptureDeviceTest : public testing::Test, ...@@ -114,11 +129,11 @@ class MediaInternalsVideoCaptureDeviceTest : public testing::Test,
: update_cb_(base::Bind( : update_cb_(base::Bind(
&MediaInternalsVideoCaptureDeviceTest::UpdateCallbackImpl, &MediaInternalsVideoCaptureDeviceTest::UpdateCallbackImpl,
base::Unretained(this))) { base::Unretained(this))) {
media_internals_->AddUpdateCallback(update_cb_); media_internals()->AddUpdateCallback(update_cb_);
} }
~MediaInternalsVideoCaptureDeviceTest() override { ~MediaInternalsVideoCaptureDeviceTest() override {
media_internals_->RemoveUpdateCallback(update_cb_); media_internals()->RemoveUpdateCallback(update_cb_);
} }
protected: protected:
...@@ -176,7 +191,7 @@ TEST_F(MediaInternalsVideoCaptureDeviceTest, ...@@ -176,7 +191,7 @@ TEST_F(MediaInternalsVideoCaptureDeviceTest,
// a JSON array of objects to string. So here, the |UpdateCallbackImpl| will // a JSON array of objects to string. So here, the |UpdateCallbackImpl| will
// deserialize the first object in the array. This means we have to have // deserialize the first object in the array. This means we have to have
// exactly one device_info in the |descriptors_and_formats|. // exactly one device_info in the |descriptors_and_formats|.
media_internals_->UpdateVideoCaptureDeviceCapabilities( media_internals()->UpdateVideoCaptureDeviceCapabilities(
descriptors_and_formats); descriptors_and_formats);
#if defined(OS_LINUX) #if defined(OS_LINUX)
...@@ -208,13 +223,13 @@ class MediaInternalsAudioLogTest ...@@ -208,13 +223,13 @@ class MediaInternalsAudioLogTest
base::Unretained(this))), base::Unretained(this))),
test_params_(MakeAudioParams()), test_params_(MakeAudioParams()),
test_component_(GetParam()), test_component_(GetParam()),
audio_log_(media_internals_->CreateAudioLog(test_component_, audio_log_(media_internals()->CreateAudioLog(test_component_,
kTestComponentID)) { kTestComponentID)) {
media_internals_->AddUpdateCallback(update_cb_); media_internals()->AddUpdateCallback(update_cb_);
} }
virtual ~MediaInternalsAudioLogTest() { virtual ~MediaInternalsAudioLogTest() {
media_internals_->RemoveUpdateCallback(update_cb_); media_internals()->RemoveUpdateCallback(update_cb_);
} }
protected: protected:
...@@ -309,13 +324,12 @@ class MediaInternalsAudioFocusTest : public testing::Test, ...@@ -309,13 +324,12 @@ class MediaInternalsAudioFocusTest : public testing::Test,
base::BindRepeating(&MediaInternalsAudioFocusTest::UpdateCallbackImpl, base::BindRepeating(&MediaInternalsAudioFocusTest::UpdateCallbackImpl,
base::Unretained(this)); base::Unretained(this));
scoped_command_line_.GetProcessCommandLine()->AppendSwitch( browser_context_.reset(new TestBrowserContext());
media_session::switches::kEnableAudioFocus); run_loop_ = std::make_unique<base::RunLoop>();
run_loop_ = std::make_unique<base::RunLoop>(); run_loop_ = std::make_unique<base::RunLoop>();
content::MediaInternals::GetInstance()->AddUpdateCallback(update_cb_); content::MediaInternals::GetInstance()->AddUpdateCallback(update_cb_);
browser_context_.reset(new TestBrowserContext());
} }
void TearDown() override { void TearDown() override {
...@@ -325,20 +339,32 @@ class MediaInternalsAudioFocusTest : public testing::Test, ...@@ -325,20 +339,32 @@ class MediaInternalsAudioFocusTest : public testing::Test,
protected: protected:
void UpdateCallbackImpl(const base::string16& update) override { void UpdateCallbackImpl(const base::string16& update) override {
base::AutoLock auto_lock(lock_);
MediaInternalsTestBase::UpdateCallbackImpl(update); MediaInternalsTestBase::UpdateCallbackImpl(update);
run_loop_->Quit(); call_count_++;
if (call_count_ == wanted_call_count_)
run_loop_->Quit();
} }
void ExpectValueAndReset(base::ListValue expected_list) { void ExpectValueAndReset(base::ListValue expected_list) {
base::AutoLock auto_lock(lock_);
base::DictionaryValue expected_data; base::DictionaryValue expected_data;
expected_data.SetKey("sessions", std::move(expected_list)); expected_data.SetKey("sessions", std::move(expected_list));
EXPECT_EQ(expected_data, update_data_); EXPECT_EQ(expected_data, update_data_);
Reset();
update_data_.Clear();
run_loop_ = std::make_unique<base::RunLoop>();
call_count_ = 0;
} }
void Reset() { void Reset() {
base::AutoLock auto_lock(lock_);
update_data_.Clear(); update_data_.Clear();
run_loop_ = std::make_unique<base::RunLoop>(); run_loop_ = std::make_unique<base::RunLoop>();
call_count_ = 0;
} }
std::unique_ptr<TestWebContents> CreateWebContents() { std::unique_ptr<TestWebContents> CreateWebContents() {
...@@ -356,9 +382,14 @@ class MediaInternalsAudioFocusTest : public testing::Test, ...@@ -356,9 +382,14 @@ class MediaInternalsAudioFocusTest : public testing::Test,
session->RemoveAllPlayersForTest(); session->RemoveAllPlayersForTest();
} }
void WaitForCallback() { void WaitForCallbackCount(int count) {
if (!update_data_.empty()) wanted_call_count_ = count;
return;
{
base::AutoLock auto_lock(lock_);
if (!update_data_.empty() && call_count_ == wanted_call_count_)
return;
}
run_loop_->Run(); run_loop_->Run();
} }
...@@ -366,8 +397,11 @@ class MediaInternalsAudioFocusTest : public testing::Test, ...@@ -366,8 +397,11 @@ class MediaInternalsAudioFocusTest : public testing::Test,
MediaInternals::UpdateCallback update_cb_; MediaInternals::UpdateCallback update_cb_;
private: private:
int call_count_ = 0;
int wanted_call_count_ = 0;
base::Lock lock_;
std::unique_ptr<base::RunLoop> run_loop_; std::unique_ptr<base::RunLoop> run_loop_;
base::test::ScopedCommandLine scoped_command_line_;
std::unique_ptr<TestBrowserContext> browser_context_; std::unique_ptr<TestBrowserContext> browser_context_;
}; };
...@@ -377,7 +411,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) { ...@@ -377,7 +411,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
web_contents1->SetTitle(base::UTF8ToUTF16(kTestTitle1)); web_contents1->SetTitle(base::UTF8ToUTF16(kTestTitle1));
MediaSessionImpl* media_session1 = MediaSessionImpl::Get(web_contents1.get()); MediaSessionImpl* media_session1 = MediaSessionImpl::Get(web_contents1.get());
media_session1->RequestSystemAudioFocus(AudioFocusType::kGain); media_session1->RequestSystemAudioFocus(AudioFocusType::kGain);
WaitForCallback(); WaitForCallbackCount(1);
// Check JSON is what we expect. // Check JSON is what we expect.
{ {
...@@ -398,9 +432,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) { ...@@ -398,9 +432,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
MediaSessionImpl* media_session2 = MediaSessionImpl::Get(web_contents2.get()); MediaSessionImpl* media_session2 = MediaSessionImpl::Get(web_contents2.get());
media_session2->RequestSystemAudioFocus( media_session2->RequestSystemAudioFocus(
AudioFocusType::kGainTransientMayDuck); AudioFocusType::kGainTransientMayDuck);
WaitForCallback(); WaitForCallbackCount(2);
Reset();
WaitForCallback();
// Check JSON is what we expect. // Check JSON is what we expect.
{ {
...@@ -424,7 +456,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) { ...@@ -424,7 +456,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
// Abandon audio focus. // Abandon audio focus.
RemoveAllPlayersForTest(media_session2); RemoveAllPlayersForTest(media_session2);
WaitForCallback(); WaitForCallbackCount(1);
// Check JSON is what we expect. // Check JSON is what we expect.
{ {
...@@ -441,7 +473,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) { ...@@ -441,7 +473,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
// Abandon audio focus. // Abandon audio focus.
RemoveAllPlayersForTest(media_session1); RemoveAllPlayersForTest(media_session1);
WaitForCallback(); WaitForCallbackCount(1);
// Check JSON is what we expect. // Check JSON is what we expect.
{ {
......
...@@ -5,13 +5,7 @@ ...@@ -5,13 +5,7 @@
#ifndef CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_H_ #ifndef CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_H_
#define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_H_ #define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_DELEGATE_H_
#include "content/browser/media/session/audio_focus_manager.h" #include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace media_session {
namespace mojom {
enum class AudioFocusType;
} // namespace mojom
} // namespace media_session
namespace content { namespace content {
...@@ -40,6 +34,10 @@ class AudioFocusDelegate { ...@@ -40,6 +34,10 @@ class AudioFocusDelegate {
// Retrieves the current |AudioFocusType| for the associated |MediaSession|. // Retrieves the current |AudioFocusType| for the associated |MediaSession|.
virtual base::Optional<media_session::mojom::AudioFocusType> virtual base::Optional<media_session::mojom::AudioFocusType>
GetCurrentFocusType() const = 0; GetCurrentFocusType() const = 0;
// |MediaSession| should call this when it's state changes.
virtual void MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr) = 0;
}; };
} // namespace content } // namespace content
......
...@@ -54,6 +54,10 @@ class AudioFocusDelegateAndroid : public AudioFocusDelegate { ...@@ -54,6 +54,10 @@ class AudioFocusDelegateAndroid : public AudioFocusDelegate {
void RecordSessionDuck(JNIEnv* env, void RecordSessionDuck(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj); const base::android::JavaParamRef<jobject>& obj);
// This is not used by this delegate.
void MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr) override {}
private: private:
// Weak pointer because |this| is owned by |media_session_|. // Weak pointer because |this| is owned by |media_session_|.
MediaSessionImpl* media_session_; MediaSessionImpl* media_session_;
......
...@@ -4,10 +4,13 @@ ...@@ -4,10 +4,13 @@
#include "content/browser/media/session/audio_focus_delegate.h" #include "content/browser/media/session/audio_focus_delegate.h"
#include "content/browser/media/session/audio_focus_manager.h"
#include "content/browser/media/session/media_session_impl.h" #include "content/browser/media/session/media_session_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/service_manager_connection.h"
#include "services/media_session/public/cpp/switches.h" #include "services/media_session/public/cpp/switches.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h" #include "services/media_session/public/mojom/audio_focus.mojom.h"
#include "services/media_session/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace content { namespace content {
...@@ -25,73 +28,130 @@ class AudioFocusDelegateDefault : public AudioFocusDelegate { ...@@ -25,73 +28,130 @@ class AudioFocusDelegateDefault : public AudioFocusDelegate {
// AudioFocusDelegate implementation. // AudioFocusDelegate implementation.
AudioFocusResult RequestAudioFocus(AudioFocusType audio_focus_type) override; AudioFocusResult RequestAudioFocus(AudioFocusType audio_focus_type) override;
void AbandonAudioFocus() override; void AbandonAudioFocus() override;
base::Optional<AudioFocusType> GetCurrentFocusType() const override; base::Optional<media_session::mojom::AudioFocusType> GetCurrentFocusType()
const override;
void MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr) override;
private: private:
// Holds the current audio focus request id for |media_session_|. // Finishes an async audio focus request.
base::Optional<AudioFocusManager::RequestId> request_id_; void FinishAudioFocusRequest(AudioFocusType type);
// Ensures that |audio_focus_ptr_| is connected.
void EnsureServiceConnection();
// Holds the latest MediaSessionInfo for |media_session_|.
media_session::mojom::MediaSessionInfoPtr session_info_;
// Holds a pointer to the Media Session service.
media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
// If the media session has acquired audio focus then this will contain a
// pointer to that requests AudioFocusRequestClient.
media_session::mojom::AudioFocusRequestClientPtr request_client_ptr_;
// Weak pointer because |this| is owned by |media_session_|. // Weak pointer because |this| is owned by |media_session_|.
MediaSessionImpl* media_session_; MediaSessionImpl* media_session_;
// The last requested AudioFocusType by the associated |media_session_|. // The last requested AudioFocusType by the associated |media_session_|.
base::Optional<AudioFocusType> audio_focus_type_if_disabled_; base::Optional<AudioFocusType> audio_focus_type_;
}; };
} // anonymous namespace } // anonymous namespace
AudioFocusDelegateDefault::AudioFocusDelegateDefault( AudioFocusDelegateDefault::AudioFocusDelegateDefault(
MediaSessionImpl* media_session) MediaSessionImpl* media_session)
: media_session_(media_session) {} : media_session_(media_session) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
AudioFocusDelegateDefault::~AudioFocusDelegateDefault() = default; AudioFocusDelegateDefault::~AudioFocusDelegateDefault() = default;
AudioFocusDelegate::AudioFocusResult AudioFocusDelegate::AudioFocusResult
AudioFocusDelegateDefault::RequestAudioFocus(AudioFocusType audio_focus_type) { AudioFocusDelegateDefault::RequestAudioFocus(AudioFocusType audio_focus_type) {
audio_focus_type_if_disabled_ = audio_focus_type; DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!media_session::IsAudioFocusEnabled()) if (!media_session::IsAudioFocusEnabled()) {
audio_focus_type_ = audio_focus_type;
return AudioFocusDelegate::AudioFocusResult::kSuccess; return AudioFocusDelegate::AudioFocusResult::kSuccess;
}
if (request_client_ptr_.is_bound()) {
// We have an existing request so we should request an updated focus type.
request_client_ptr_->RequestAudioFocus(
session_info_.Clone(), audio_focus_type,
base::BindOnce(&AudioFocusDelegateDefault::FinishAudioFocusRequest,
base::Unretained(this), audio_focus_type));
} else {
EnsureServiceConnection();
// Create a mojo interface pointer to our media session.
media_session::mojom::MediaSessionPtr media_session;
media_session_->BindToMojoRequest(mojo::MakeRequest(&media_session));
audio_focus_ptr_->RequestAudioFocus(
mojo::MakeRequest(&request_client_ptr_), std::move(media_session),
session_info_.Clone(), audio_focus_type,
base::BindOnce(&AudioFocusDelegateDefault::FinishAudioFocusRequest,
base::Unretained(this), audio_focus_type));
}
// Return delayed as we make the async call to request audio focus.
return AudioFocusDelegate::AudioFocusResult::kDelayed;
}
media_session::mojom::MediaSessionInfoPtr session_info = void AudioFocusDelegateDefault::AbandonAudioFocus() {
media_session_->GetMediaSessionInfoSync(); DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Create a mojo interface pointer to our media session. This will allow the audio_focus_type_.reset();
// AudioFocusManager to interact with the media session across processes.
media_session::mojom::MediaSessionPtr media_session;
media_session_->BindToMojoRequest(mojo::MakeRequest(&media_session));
AudioFocusManager::RequestResponse response = if (!request_client_ptr_.is_bound())
AudioFocusManager::GetInstance()->RequestAudioFocus( return;
std::move(media_session), std::move(session_info), audio_focus_type,
request_id_);
request_id_ = response.first; request_client_ptr_->AbandonAudioFocus();
request_client_ptr_.reset();
}
return response.second ? AudioFocusDelegate::AudioFocusResult::kSuccess base::Optional<media_session::mojom::AudioFocusType>
: AudioFocusDelegate::AudioFocusResult::kFailed; AudioFocusDelegateDefault::GetCurrentFocusType() const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return audio_focus_type_;
} }
void AudioFocusDelegateDefault::AbandonAudioFocus() { void AudioFocusDelegateDefault::MediaSessionInfoChanged(
audio_focus_type_if_disabled_.reset(); media_session::mojom::MediaSessionInfoPtr session_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!request_id_.has_value()) if (request_client_ptr_.is_bound())
return; request_client_ptr_->MediaSessionInfoChanged(session_info.Clone());
session_info_ = std::move(session_info);
}
void AudioFocusDelegateDefault::FinishAudioFocusRequest(AudioFocusType type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(request_client_ptr_.is_bound());
AudioFocusManager::GetInstance()->AbandonAudioFocus(request_id_.value()); audio_focus_type_ = type;
request_id_.reset(); media_session_->FinishSystemAudioFocusRequest(type, true /* result */);
} }
base::Optional<AudioFocusType> AudioFocusDelegateDefault::GetCurrentFocusType() void AudioFocusDelegateDefault::EnsureServiceConnection() {
const { DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!media_session::IsAudioFocusEnabled()) if (!media_session::IsAudioFocusEnabled())
return audio_focus_type_if_disabled_; return;
if (audio_focus_ptr_.is_bound() && !audio_focus_ptr_.encountered_error())
return;
if (!request_id_.has_value()) audio_focus_ptr_.reset();
return base::Optional<AudioFocusType>();
return AudioFocusManager::GetInstance()->GetFocusTypeForSession( // Connect to the Media Session service and bind |audio_focus_ptr_| to it.
request_id_.value()); service_manager::Connector* connector =
ServiceManagerConnection::GetForProcess()->GetConnector();
connector->BindInterface(media_session::mojom::kServiceName,
mojo::MakeRequest(&audio_focus_ptr_));
} }
// static // static
......
...@@ -3,18 +3,75 @@ ...@@ -3,18 +3,75 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "base/command_line.h" #include "base/command_line.h"
#include "content/browser/media/session/audio_focus_test_util.h"
#include "content/browser/media/session/media_session_impl.h" #include "content/browser/media/session/media_session_impl.h"
#include "content/browser/media/session/mock_media_session_player_observer.h" #include "content/browser/media/session/mock_media_session_player_observer.h"
#include "content/public/common/service_manager_connection.h"
#include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test.h"
#include "content/shell/browser/shell.h" #include "content/shell/browser/shell.h"
#include "media/base/media_content_type.h" #include "media/base/media_content_type.h"
#include "services/media_session/public/cpp/switches.h" #include "services/media_session/public/cpp/switches.h"
#include "services/media_session/public/cpp/test/audio_focus_test_util.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
#include "services/media_session/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace content { namespace content {
using media_session::test::TestAudioFocusObserver;
class MediaSessionStateObserver
: public media_session::mojom::MediaSessionObserver {
public:
explicit MediaSessionStateObserver(
media_session::mojom::MediaSession* media_session)
: binding_(this) {
media_session::mojom::MediaSessionObserverPtr observer;
binding_.Bind(mojo::MakeRequest(&observer));
media_session->AddObserver(std::move(observer));
}
~MediaSessionStateObserver() override = default;
// media_session::mojom::MediaSessionObserver
void MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr session_info) override {
if (desired_state_.has_value() &&
desired_state_.value() == session_info->state) {
run_loop_.Quit();
return;
}
session_info_ = std::move(session_info);
}
void WaitForState(
media_session::mojom::MediaSessionInfo::SessionState state) {
if (session_info_ && state == session_info_->state)
return;
desired_state_ = state;
run_loop_.Run();
}
protected:
base::RunLoop run_loop_;
mojo::Binding<media_session::mojom::MediaSessionObserver> binding_;
base::Optional<media_session::mojom::MediaSessionInfo::SessionState>
desired_state_;
media_session::mojom::MediaSessionInfoPtr session_info_;
DISALLOW_COPY_AND_ASSIGN(MediaSessionStateObserver);
};
class AudioFocusDelegateDefaultBrowserTest : public ContentBrowserTest { class AudioFocusDelegateDefaultBrowserTest : public ContentBrowserTest {
protected: protected:
void SetUpOnMainThread() override {
service_manager::Connector* connector =
ServiceManagerConnection::GetForProcess()->GetConnector();
connector->BindInterface(media_session::mojom::kServiceName,
mojo::MakeRequest(&audio_focus_ptr_));
}
void SetUpCommandLine(base::CommandLine* command_line) override { void SetUpCommandLine(base::CommandLine* command_line) override {
command_line->AppendSwitch(media_session::switches::kEnableAudioFocus); command_line->AppendSwitch(media_session::switches::kEnableAudioFocus);
} }
...@@ -33,30 +90,77 @@ class AudioFocusDelegateDefaultBrowserTest : public ContentBrowserTest { ...@@ -33,30 +90,77 @@ class AudioFocusDelegateDefaultBrowserTest : public ContentBrowserTest {
player_observer->StartNewPlayer(); player_observer->StartNewPlayer();
{ {
test::TestAudioFocusObserver observer; std::unique_ptr<TestAudioFocusObserver> observer = CreateObserver();
media_session->AddPlayer(player_observer.get(), 0, media_session->AddPlayer(player_observer.get(), 0,
media::MediaContentType::Persistent); media::MediaContentType::Persistent);
observer.WaitForGainedEvent(); observer->WaitForGainedEvent();
} }
EXPECT_TRUE(media_session->IsActive()); {
EXPECT_FALSE(other_media_session->IsActive()); MediaSessionStateObserver state_observer(media_session);
state_observer.WaitForState(
media_session::mojom::MediaSessionInfo::SessionState::kActive);
}
{
MediaSessionStateObserver state_observer(other_media_session);
state_observer.WaitForState(
media_session::mojom::MediaSessionInfo::SessionState::kInactive);
}
player_observer->StartNewPlayer(); player_observer->StartNewPlayer();
{ {
test::TestAudioFocusObserver observer; std::unique_ptr<TestAudioFocusObserver> observer = CreateObserver();
other_media_session->AddPlayer(player_observer.get(), 1, other_media_session->AddPlayer(player_observer.get(), 1,
media::MediaContentType::Persistent); media::MediaContentType::Persistent);
observer.WaitForGainedEvent(); observer->WaitForGainedEvent();
}
{
MediaSessionStateObserver state_observer(media_session);
state_observer.WaitForState(
media_session::mojom::MediaSessionInfo::SessionState::kSuspended);
}
{
MediaSessionStateObserver state_observer(other_media_session);
state_observer.WaitForState(
media_session::mojom::MediaSessionInfo::SessionState::kActive);
}
{
std::unique_ptr<TestAudioFocusObserver> observer = CreateObserver();
media_session->Stop(MediaSessionImpl::SuspendType::kUI);
other_media_session->Stop(MediaSessionImpl::SuspendType::kUI);
observer->WaitForLostEvent();
} }
EXPECT_FALSE(media_session->IsActive()); {
EXPECT_TRUE(other_media_session->IsActive()); MediaSessionStateObserver state_observer(media_session);
state_observer.WaitForState(
media_session::mojom::MediaSessionInfo::SessionState::kInactive);
}
media_session->Stop(MediaSessionImpl::SuspendType::kUI); {
other_media_session->Stop(MediaSessionImpl::SuspendType::kUI); MediaSessionStateObserver state_observer(other_media_session);
state_observer.WaitForState(
media_session::mojom::MediaSessionInfo::SessionState::kInactive);
}
}
private:
std::unique_ptr<TestAudioFocusObserver> CreateObserver() {
std::unique_ptr<TestAudioFocusObserver> observer =
std::make_unique<TestAudioFocusObserver>();
media_session::mojom::AudioFocusObserverPtr observer_ptr;
observer->BindToMojoRequest(mojo::MakeRequest(&observer_ptr));
audio_focus_ptr_->AddObserver(std::move(observer_ptr));
audio_focus_ptr_.FlushForTesting();
return observer;
} }
media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
}; };
// Two windows from the same BrowserContext. // Two windows from the same BrowserContext.
......
...@@ -336,23 +336,6 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_NoAssociatedEntry) { ...@@ -336,23 +336,6 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_NoAssociatedEntry) {
EXPECT_EQ(kNoFocusedSession, GetAudioFocusedSession()); EXPECT_EQ(kNoFocusedSession, GetAudioFocusedSession());
} }
TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientEntry) {
MockMediaSession media_session;
AudioFocusManager::RequestId request_id =
RequestAudioFocus(&media_session, AudioFocusType::kGainTransientMayDuck);
EXPECT_EQ(1, GetTransientMaybeDuckCount());
{
test::TestAudioFocusObserver observer;
AbandonAudioFocus(request_id);
EXPECT_EQ(0, GetTransientMaybeDuckCount());
EXPECT_TRUE(observer.focus_lost_session_.Equals(
test::GetMediaSessionInfoSync(&media_session)));
}
}
TEST_F(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) { TEST_F(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
MockMediaSession media_session_1; MockMediaSession media_session_1;
MockMediaSession media_session_2; MockMediaSession media_session_2;
...@@ -528,51 +511,4 @@ TEST_F(AudioFocusManagerTest, AudioFocusObserver_AbandonNoop) { ...@@ -528,51 +511,4 @@ TEST_F(AudioFocusManagerTest, AudioFocusObserver_AbandonNoop) {
EXPECT_TRUE(observer.focus_lost_session_.is_null()); EXPECT_TRUE(observer.focus_lost_session_.is_null());
} }
TEST_F(AudioFocusManagerTest, AudioFocusObserver_RequestNoop) {
MockMediaSession media_session;
AudioFocusManager::RequestId request_id;
{
test::TestAudioFocusObserver observer;
request_id = RequestAudioFocus(&media_session, AudioFocusType::kGain);
EXPECT_EQ(request_id, GetAudioFocusedSession());
EXPECT_EQ(AudioFocusType::kGain, observer.focus_gained_type());
EXPECT_FALSE(observer.focus_gained_session_.is_null());
}
{
test::TestAudioFocusObserver observer;
RequestAudioFocus(&media_session, AudioFocusType::kGain, request_id);
EXPECT_EQ(request_id, GetAudioFocusedSession());
EXPECT_TRUE(observer.focus_gained_session_.is_null());
}
}
TEST_F(AudioFocusManagerTest, AudioFocusObserver_TransientMayDuck) {
MockMediaSession media_session;
AudioFocusManager::RequestId request_id;
{
test::TestAudioFocusObserver observer;
request_id = RequestAudioFocus(&media_session,
AudioFocusType::kGainTransientMayDuck);
EXPECT_EQ(1, GetTransientMaybeDuckCount());
EXPECT_EQ(AudioFocusType::kGainTransientMayDuck,
observer.focus_gained_type());
EXPECT_FALSE(observer.focus_gained_session_.is_null());
}
{
test::TestAudioFocusObserver observer;
AbandonAudioFocus(request_id);
EXPECT_EQ(0, GetTransientMaybeDuckCount());
EXPECT_TRUE(observer.focus_lost_session_.Equals(
test::GetMediaSessionInfoSync(&media_session)));
}
}
} // namespace content } // namespace content
...@@ -4,41 +4,52 @@ ...@@ -4,41 +4,52 @@
#include "content/browser/media/session/audio_focus_observer.h" #include "content/browser/media/session/audio_focus_observer.h"
#include "build/build_config.h"
#include "content/browser/media/session/audio_focus_manager.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/common/service_manager_connection.h"
#include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/public/cpp/bindings/interface_request.h"
#include "services/media_session/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
namespace content { namespace content {
AudioFocusObserver::AudioFocusObserver() : binding_(this) {} AudioFocusObserver::AudioFocusObserver() : binding_(this) {}
void AudioFocusObserver::RegisterAudioFocusObserver() { void AudioFocusObserver::RegisterAudioFocusObserver() {
if (observer_id_.has_value()) ConnectToService();
if (!audio_focus_ptr_.is_bound() || audio_focus_ptr_.encountered_error())
return;
if (binding_.is_bound())
return; return;
#if !defined(OS_ANDROID)
// TODO(https://crbug.com/873320): Add support for Android.
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
media_session::mojom::AudioFocusObserverPtr observer; media_session::mojom::AudioFocusObserverPtr observer;
binding_.Bind(mojo::MakeRequest(&observer)); binding_.Bind(mojo::MakeRequest(&observer));
observer_id_ = audio_focus_ptr_->AddObserver(std::move(observer));
AudioFocusManager::GetInstance()->AddObserver(std::move(observer));
#endif
} }
void AudioFocusObserver::UnregisterAudioFocusObserver() { void AudioFocusObserver::UnregisterAudioFocusObserver() {
if (!observer_id_.has_value())
return;
#if !defined(OS_ANDROID)
// TODO(https://crbug.com/873320): Add support for Android.
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
binding_.Close(); binding_.Close();
AudioFocusManager::GetInstance()->RemoveObserver(observer_id_.value()); }
#endif
void AudioFocusObserver::ConnectToService() {
if (audio_focus_ptr_.encountered_error())
audio_focus_ptr_.reset();
if (audio_focus_ptr_.is_bound())
return;
ServiceManagerConnection* connection =
ServiceManagerConnection::GetForProcess();
if (!connection)
return;
observer_id_.reset(); service_manager::Connector* connector = connection->GetConnector();
connector->BindInterface(media_session::mojom::kServiceName,
mojo::MakeRequest(&audio_focus_ptr_));
} }
AudioFocusObserver::~AudioFocusObserver() = default; AudioFocusObserver::~AudioFocusObserver() = default;
......
...@@ -6,10 +6,8 @@ ...@@ -6,10 +6,8 @@
#define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_OBSERVER_H_ #define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_OBSERVER_H_
#include "base/macros.h" #include "base/macros.h"
#include "base/optional.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h" #include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content { namespace content {
...@@ -35,7 +33,8 @@ class CONTENT_EXPORT AudioFocusObserver ...@@ -35,7 +33,8 @@ class CONTENT_EXPORT AudioFocusObserver
void UnregisterAudioFocusObserver(); void UnregisterAudioFocusObserver();
private: private:
base::Optional<mojo::InterfacePtrSetElementId> observer_id_; void ConnectToService();
media_session::mojom::AudioFocusManagerPtr audio_focus_ptr_;
mojo::Binding<media_session::mojom::AudioFocusObserver> binding_; mojo::Binding<media_session::mojom::AudioFocusObserver> binding_;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/command_line.h" #include "base/command_line.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "content/browser/media/session/media_session_controller.h" #include "content/browser/media/session/media_session_controller.h"
#include "content/public/test/test_service_manager_context.h"
#include "content/test/test_render_view_host.h" #include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h" #include "content/test/test_web_contents.h"
#include "media/base/media_content_type.h" #include "media/base/media_content_type.h"
...@@ -54,6 +55,8 @@ class MediaSessionControllersManagerTest ...@@ -54,6 +55,8 @@ class MediaSessionControllersManagerTest
} }
#endif #endif
service_manager_context_ = std::make_unique<TestServiceManagerContext>();
media_player_id_ = MediaSessionControllersManager::MediaPlayerId( media_player_id_ = MediaSessionControllersManager::MediaPlayerId(
contents()->GetMainFrame(), 1); contents()->GetMainFrame(), 1);
mock_media_session_controller_ = mock_media_session_controller_ =
...@@ -86,6 +89,7 @@ class MediaSessionControllersManagerTest ...@@ -86,6 +89,7 @@ class MediaSessionControllersManagerTest
void TearDown() override { void TearDown() override {
manager_.reset(); manager_.reset();
service_manager_context_.reset();
RenderViewHostImplTestHarness::TearDown(); RenderViewHostImplTestHarness::TearDown();
} }
...@@ -98,6 +102,7 @@ class MediaSessionControllersManagerTest ...@@ -98,6 +102,7 @@ class MediaSessionControllersManagerTest
StrictMock<MockMediaSessionController>* mock_media_session_controller_ptr_ = StrictMock<MockMediaSessionController>* mock_media_session_controller_ptr_ =
nullptr; nullptr;
std::unique_ptr<MediaSessionControllersManager> manager_; std::unique_ptr<MediaSessionControllersManager> manager_;
std::unique_ptr<TestServiceManagerContext> service_manager_context_;
}; };
TEST_P(MediaSessionControllersManagerTest, RequestPlayAddsSessionsToMap) { TEST_P(MediaSessionControllersManagerTest, RequestPlayAddsSessionsToMap) {
......
...@@ -626,6 +626,7 @@ MediaSessionImpl::MediaSessionImpl(WebContents* web_contents) ...@@ -626,6 +626,7 @@ MediaSessionImpl::MediaSessionImpl(WebContents* web_contents)
void MediaSessionImpl::Initialize() { void MediaSessionImpl::Initialize() {
delegate_ = AudioFocusDelegate::Create(this); delegate_ = AudioFocusDelegate::Create(this);
delegate_->MediaSessionInfoChanged(GetMediaSessionInfoSync());
} }
AudioFocusDelegate::AudioFocusResult MediaSessionImpl::RequestSystemAudioFocus( AudioFocusDelegate::AudioFocusResult MediaSessionImpl::RequestSystemAudioFocus(
...@@ -798,6 +799,8 @@ void MediaSessionImpl::NotifyObserversInfoChanged() { ...@@ -798,6 +799,8 @@ void MediaSessionImpl::NotifyObserversInfoChanged() {
[&current_info](media_session::mojom::MediaSessionObserver* observer) { [&current_info](media_session::mojom::MediaSessionObserver* observer) {
observer->MediaSessionInfoChanged(current_info.Clone()); observer->MediaSessionInfoChanged(current_info.Clone());
}); });
delegate_->MediaSessionInfoChanged(current_info.Clone());
} }
bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer, bool MediaSessionImpl::AddPepperPlayer(MediaSessionPlayerObserver* observer,
......
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/optional.h" #include "base/optional.h"
#include "content/browser/media/session/audio_focus_delegate.h" #include "content/browser/media/session/audio_focus_delegate.h"
#include "content/browser/media/session/audio_focus_manager.h"
#include "content/browser/media/session/media_session_uma_helper.h" #include "content/browser/media/session/media_session_uma_helper.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/public/browser/media_session.h" #include "content/public/browser/media_session.h"
......
...@@ -71,6 +71,9 @@ class MockAudioFocusDelegate : public AudioFocusDelegate { ...@@ -71,6 +71,9 @@ class MockAudioFocusDelegate : public AudioFocusDelegate {
return audio_focus_type_; return audio_focus_type_;
} }
void MediaSessionInfoChanged(
media_session::mojom::MediaSessionInfoPtr session_info) override {}
void ResolveRequest(bool result) { void ResolveRequest(bool result) {
if (!async_mode_) if (!async_mode_)
return; return;
......
...@@ -313,6 +313,7 @@ jumbo_static_library("test_support") { ...@@ -313,6 +313,7 @@ jumbo_static_library("test_support") {
"//ipc", "//ipc",
"//media/mojo/clients", "//media/mojo/clients",
"//media/mojo/interfaces", "//media/mojo/interfaces",
"//services/media_session/public/cpp/test:test_support",
"//services/media_session/public/mojom", "//services/media_session/public/mojom",
"//third_party/blink/public:blink", "//third_party/blink/public:blink",
"//third_party/blink/public:test_support", "//third_party/blink/public:test_support",
......
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