Commit 8da7a66a authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

[Media Session] Mojoify audio focus observer

Move AudioFocusObserver to the media session service and
convert it to use mojo. At the moment the observers
register themselves with AudioFocusManager but in the
future this will be with the Media Sesssion service.

Also adds an empty MediaSession mojo type so we can pass
it as an arg to AudioFocusObserver.

BUG=875004

Change-Id: I4bd09796018833cb9f9714b2296642bd40be48ff
Reviewed-on: https://chromium-review.googlesource.com/1180484
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Reviewed-by: default avatarNick Carter <nick@chromium.org>
Reviewed-by: default avatarMounir Lamouri <mlamouri@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#586012}
parent 3da2da6a
......@@ -647,6 +647,8 @@ void MediaInternals::AddUpdateCallback(const UpdateCallback& callback) {
base::AutoLock auto_lock(lock_);
can_update_ = true;
RegisterAudioFocusObserver();
}
void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
......@@ -660,6 +662,9 @@ void MediaInternals::RemoveUpdateCallback(const UpdateCallback& callback) {
base::AutoLock auto_lock(lock_);
can_update_ = !update_callbacks_.empty();
if (!can_update_)
UnregisterAudioFocusObserver();
}
bool MediaInternals::CanUpdate() {
......@@ -700,8 +705,8 @@ void MediaInternals::SendVideoCaptureDeviceCapabilities() {
&video_capture_capabilities_cached_data_));
}
#if !defined(OS_ANDROID)
void MediaInternals::SendAudioFocusState() {
#if !defined(OS_ANDROID)
if (!CanUpdate())
return;
......@@ -725,8 +730,8 @@ void MediaInternals::SendAudioFocusState() {
SendUpdate(
SerializeUpdate("media.onReceiveAudioFocusState", &audio_focus_data));
}
#endif // !defined(OS_ANDROID)
}
void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
const std::vector<std::tuple<media::VideoCaptureDeviceDescriptor,
......@@ -808,8 +813,8 @@ void MediaInternals::OnProcessTerminatedForTesting(int process_id) {
uma_handler_->OnProcessTerminated(process_id);
}
#if !defined(OS_ANDROID)
void MediaInternals::OnFocusGained(MediaSession* media_session,
void MediaInternals::OnFocusGained(
media_session::mojom::MediaSessionPtr media_session,
media_session::mojom::AudioFocusType type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
......@@ -818,14 +823,14 @@ void MediaInternals::OnFocusGained(MediaSession* media_session,
base::Unretained(this)));
}
void MediaInternals::OnFocusLost(MediaSession* media_session) {
void MediaInternals::OnFocusLost(
media_session::mojom::MediaSessionPtr media_session) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::BindOnce(&MediaInternals::SendAudioFocusState,
base::Unretained(this)));
}
#endif // !defined(OS_ANDROID)
void MediaInternals::SendUpdate(const base::string16& update) {
// SendUpdate() may be called from any thread, but must run on the UI thread.
......
......@@ -18,7 +18,6 @@
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/media/session/audio_focus_observer.h"
#include "content/common/content_export.h"
#include "content/public/browser/notification_observer.h"
......@@ -45,9 +44,7 @@ namespace content {
// TODO(crbug.com/812557): Remove inheritance from media::AudioLogFactory once
// the creation of the AudioManager instance moves to the audio service.
class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
#if !defined(OS_ANDROID)
public AudioFocusObserver,
#endif
public NotificationObserver {
public:
// Called with the update string.
......@@ -85,10 +82,8 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
// UpdateCallback.
void SendVideoCaptureDeviceCapabilities();
#if !defined(OS_ANDROID)
// Sends all audio focus information to each registered UpdateCallback.
void SendAudioFocusState();
#endif
// Called to inform of the capabilities enumerated for video devices.
void UpdateVideoCaptureDeviceCapabilities(
......@@ -125,12 +120,11 @@ class CONTENT_EXPORT MediaInternals : public media::AudioLogFactory,
MediaInternals();
#if !defined(OS_ANDROID)
// AudioFocusObserver implementation.
void OnFocusGained(MediaSession* media_session,
void OnFocusGained(media_session::mojom::MediaSessionPtr media_session,
media_session::mojom::AudioFocusType type) override;
void OnFocusLost(MediaSession* media_session) override;
#endif
void OnFocusLost(
media_session::mojom::MediaSessionPtr media_session) override;
// Sends |update| to each registered UpdateCallback. Safe to call from any
// thread, but will forward to the IO thread.
......
......@@ -342,6 +342,11 @@ class MediaInternalsAudioFocusTest : public testing::Test,
session->RemoveAllPlayersForTest();
}
void WaitForCallback() {
AudioFocusManager::GetInstance()->FlushForTesting();
base::RunLoop().RunUntilIdle();
}
MediaInternals::UpdateCallback update_cb_;
private:
......@@ -355,7 +360,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
web_contents1->SetTitle(base::UTF8ToUTF16(kTestTitle1));
MediaSessionImpl* media_session1 = MediaSessionImpl::Get(web_contents1.get());
media_session1->RequestSystemAudioFocus(AudioFocusType::kGain);
base::RunLoop().RunUntilIdle();
WaitForCallback();
// Check JSON is what we expect.
{
......@@ -375,7 +380,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
MediaSessionImpl* media_session2 = MediaSessionImpl::Get(web_contents2.get());
media_session2->RequestSystemAudioFocus(
AudioFocusType::kGainTransientMayDuck);
base::RunLoop().RunUntilIdle();
WaitForCallback();
// Check JSON is what we expect.
{
......@@ -397,7 +402,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
// Abandon audio focus.
RemoveAllPlayersForTest(media_session2);
base::RunLoop().RunUntilIdle();
WaitForCallback();
// Check JSON is what we expect.
{
......@@ -413,7 +418,7 @@ TEST_F(MediaInternalsAudioFocusTest, AudioFocusStateIsUpdated) {
// Abandon audio focus.
RemoveAllPlayersForTest(media_session1);
base::RunLoop().RunUntilIdle();
WaitForCallback();
// Check JSON is what we expect.
{
......
......@@ -6,13 +6,26 @@
#include "content/browser/media/session/audio_focus_observer.h"
#include "content/browser/media/session/media_session_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content {
using AudioFocusType = media_session::mojom::AudioFocusType;
namespace {
media_session::mojom::MediaSessionPtr GetSessionMojoPtr(
MediaSessionImpl* session) {
media_session::mojom::MediaSessionPtr media_session_ptr;
session->BindToMojoRequest(mojo::MakeRequest(&media_session_ptr));
return media_session_ptr;
}
} // namespace
// static
AudioFocusManager* AudioFocusManager::GetInstance() {
return base::Singleton<AudioFocusManager>::get();
......@@ -55,8 +68,11 @@ void AudioFocusManager::RequestAudioFocus(MediaSessionImpl* media_session,
audio_focus_stack_.back()->StopDucking();
// Notify observers that we were gained audio focus.
for (AudioFocusObserver* observer : audio_focus_observers_)
observer->OnFocusGained(media_session, type);
observers_.ForAllPtrs(
[media_session,
type](media_session::mojom::AudioFocusObserver* observer) {
observer->OnFocusGained(GetSessionMojoPtr(media_session), type);
});
}
void AudioFocusManager::AbandonAudioFocus(MediaSessionImpl* media_session) {
......@@ -71,8 +87,10 @@ void AudioFocusManager::AbandonAudioFocus(MediaSessionImpl* media_session) {
audio_focus_stack_.pop_back();
if (audio_focus_stack_.empty()) {
// Notify observers that we lost audio focus.
for (AudioFocusObserver* observer : audio_focus_observers_)
observer->OnFocusLost(media_session);
observers_.ForAllPtrs(
[media_session](media_session::mojom::AudioFocusObserver* observer) {
observer->OnFocusLost(GetSessionMojoPtr(media_session));
});
return;
}
......@@ -96,19 +114,35 @@ void AudioFocusManager::AbandonAudioFocus(MediaSessionImpl* media_session) {
audio_focus_stack_.back()->StopDucking();
// Notify observers that we lost audio focus.
for (AudioFocusObserver* observer : audio_focus_observers_)
observer->OnFocusLost(media_session);
observers_.ForAllPtrs(
[media_session](media_session::mojom::AudioFocusObserver* observer) {
observer->OnFocusLost(GetSessionMojoPtr(media_session));
});
}
void AudioFocusManager::AddObserver(AudioFocusObserver* observer) {
audio_focus_observers_.push_back(observer);
mojo::InterfacePtrSetElementId AudioFocusManager::AddObserver(
media_session::mojom::AudioFocusObserverPtr observer) {
return observers_.AddPtr(std::move(observer));
}
void AudioFocusManager::RemoveObserver(AudioFocusObserver* observer) {
audio_focus_observers_.remove(observer);
void AudioFocusManager::RemoveObserver(mojo::InterfacePtrSetElementId id) {
observers_.RemovePtr(id);
}
AudioFocusManager::AudioFocusManager() = default;
void AudioFocusManager::ResetForTesting() {
audio_focus_stack_.clear();
observers_.CloseAll();
}
void AudioFocusManager::FlushForTesting() {
observers_.FlushForTesting();
}
AudioFocusManager::AudioFocusManager() {
// Make sure we start AudioFocusManager on the browser UI thread. This is to
// ensure thread consistency for mojo::InterfaceSetPtr.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
AudioFocusManager::~AudioFocusManager() = default;
......
......@@ -11,16 +11,11 @@
#include "base/memory/singleton.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
namespace media_session {
namespace mojom {
enum class AudioFocusType;
} // namespace mojom
} // namespace media_session
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace content {
class AudioFocusObserver;
class MediaSessionImpl;
class CONTENT_EXPORT AudioFocusManager {
......@@ -34,16 +29,24 @@ class CONTENT_EXPORT AudioFocusManager {
void AbandonAudioFocus(MediaSessionImpl* media_session);
// Adds/removes audio focus observers.
void AddObserver(AudioFocusObserver*);
void RemoveObserver(AudioFocusObserver*);
mojo::InterfacePtrSetElementId AddObserver(
media_session::mojom::AudioFocusObserverPtr);
void RemoveObserver(mojo::InterfacePtrSetElementId);
private:
friend struct base::DefaultSingletonTraits<AudioFocusManager>;
friend class AudioFocusManagerTest;
// Media internals UI needs access to internal state.
friend class MediaInternalsAudioFocusTest;
friend class MediaInternals;
// Flush for testing will flush any pending messages to the observers.
void FlushForTesting();
// Reset for testing will clear any built up internal state.
void ResetForTesting();
AudioFocusManager();
~AudioFocusManager();
......@@ -51,7 +54,7 @@ class CONTENT_EXPORT AudioFocusManager {
// Weak reference of managed observers. Observers are expected to remove
// themselves before being destroyed.
std::list<AudioFocusObserver*> audio_focus_observers_;
mojo::InterfacePtrSet<media_session::mojom::AudioFocusObserver> observers_;
// Weak reference of managed MediaSessions. A MediaSession must abandon audio
// focus before its destruction.
......
......@@ -7,6 +7,7 @@
#include <memory>
#include "base/command_line.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "content/browser/media/session/audio_focus_observer.h"
#include "content/browser/media/session/media_session_impl.h"
......@@ -18,19 +19,32 @@
#include "media/base/media_content_type.h"
#include "media/base/media_switches.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace content {
using AudioFocusType = media_session::mojom::AudioFocusType;
using media_session::mojom::AudioFocusType;
using media_session::mojom::MediaSessionPtr;
namespace {
class MockAudioFocusObserver : public AudioFocusObserver {
public:
MOCK_METHOD2(OnFocusGained,
void(MediaSession* media_session, AudioFocusType type));
MOCK_METHOD1(OnFocusLost, void(MediaSession* media_session));
MockAudioFocusObserver() { RegisterAudioFocusObserver(); }
void OnFocusGained(MediaSessionPtr session, AudioFocusType type) override {
EXPECT_TRUE(session.is_bound());
focus_gained_call_ = type;
focus_lost_call_ = false;
}
void OnFocusLost(MediaSessionPtr session) override {
EXPECT_TRUE(session.is_bound());
focus_lost_call_ = true;
focus_gained_call_.reset();
}
base::Optional<AudioFocusType> focus_gained_call_;
bool focus_lost_call_ = false;
};
class MockMediaSessionPlayerObserver : public MediaSessionPlayerObserver {
......@@ -60,6 +74,10 @@ class AudioFocusManagerTest : public testing::Test {
rph_factory_.get());
browser_context_.reset(new TestBrowserContext());
pepper_observer_.reset(new MockMediaSessionPlayerObserver());
// AudioFocusManager is a singleton so we should make sure we reset any
// state in between tests.
AudioFocusManager::GetInstance()->ResetForTesting();
}
void TearDown() override {
......@@ -110,6 +128,10 @@ class AudioFocusManagerTest : public testing::Test {
session->AbandonSystemAudioFocusIfNeeded();
}
void FlushForTesting() {
AudioFocusManager::GetInstance()->FlushForTesting();
}
std::unique_ptr<WebContents> CreateWebContents() {
return TestWebContents::Create(browser_context_.get(),
SiteInstance::SiteInstance::Create(browser_context_.get()));
......@@ -243,11 +265,14 @@ TEST_F(AudioFocusManagerTest, AbandonAudioFocus_RemovesTransientEntry) {
RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
ASSERT_EQ(1, GetTransientMaybeDuckCount());
{
MockAudioFocusObserver observer;
EXPECT_CALL(observer, OnFocusLost(media_session));
AbandonAudioFocus(media_session);
ASSERT_EQ(0, GetTransientMaybeDuckCount());
FlushForTesting();
EXPECT_EQ(0, GetTransientMaybeDuckCount());
EXPECT_TRUE(observer.focus_lost_call_);
}
}
TEST_F(AudioFocusManagerTest, AbandonAudioFocus_WhileDuckingThenResume) {
......@@ -465,10 +490,11 @@ TEST_F(AudioFocusManagerTest, AudioFocusObserver_AbandonNoop) {
{
MockAudioFocusObserver observer;
EXPECT_CALL(observer, OnFocusLost(media_session)).Times(0);
AbandonAudioFocus(media_session);
FlushForTesting();
EXPECT_EQ(nullptr, GetAudioFocusedSession());
EXPECT_FALSE(observer.focus_lost_call_);
}
}
......@@ -476,16 +502,22 @@ TEST_F(AudioFocusManagerTest, AudioFocusObserver_RequestNoop) {
std::unique_ptr<WebContents> web_contents(CreateWebContents());
MediaSessionImpl* media_session = MediaSessionImpl::Get(web_contents.get());
{
MockAudioFocusObserver observer;
RequestAudioFocus(media_session, AudioFocusType::kGain);
FlushForTesting();
EXPECT_EQ(media_session, GetAudioFocusedSession());
EXPECT_EQ(AudioFocusType::kGain, observer.focus_gained_call_.value());
}
{
MockAudioFocusObserver observer;
EXPECT_CALL(observer, OnFocusGained(media_session, AudioFocusType::kGain))
.Times(0);
RequestAudioFocus(media_session, AudioFocusType::kGain);
FlushForTesting();
EXPECT_EQ(media_session, GetAudioFocusedSession());
EXPECT_FALSE(observer.focus_gained_call_.has_value());
}
}
......@@ -495,19 +527,21 @@ TEST_F(AudioFocusManagerTest, AudioFocusObserver_TransientMayDuck) {
{
MockAudioFocusObserver observer;
EXPECT_CALL(observer, OnFocusGained(media_session,
AudioFocusType::kGainTransientMayDuck));
RequestAudioFocus(media_session, AudioFocusType::kGainTransientMayDuck);
FlushForTesting();
EXPECT_EQ(1, GetTransientMaybeDuckCount());
EXPECT_EQ(AudioFocusType::kGainTransientMayDuck,
observer.focus_gained_call_.value());
}
{
MockAudioFocusObserver observer;
EXPECT_CALL(observer, OnFocusLost(media_session));
AbandonAudioFocus(media_session);
FlushForTesting();
EXPECT_EQ(0, GetTransientMaybeDuckCount());
EXPECT_TRUE(observer.focus_lost_call_);
}
}
......
......@@ -6,21 +6,41 @@
#include "build/build_config.h"
#include "content/browser/media/session/audio_focus_manager.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/interface_request.h"
namespace content {
AudioFocusObserver::AudioFocusObserver() {
AudioFocusObserver::AudioFocusObserver() : binding_(this) {}
void AudioFocusObserver::RegisterAudioFocusObserver() {
if (observer_id_.has_value())
return;
#if !defined(OS_ANDROID)
// TODO(https://crbug.com/873320): Add support for Android.
AudioFocusManager::GetInstance()->AddObserver(this);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
media_session::mojom::AudioFocusObserverPtr observer;
binding_.Bind(mojo::MakeRequest(&observer));
observer_id_ =
AudioFocusManager::GetInstance()->AddObserver(std::move(observer));
#endif
}
AudioFocusObserver::~AudioFocusObserver() {
void AudioFocusObserver::UnregisterAudioFocusObserver() {
if (!observer_id_.has_value())
return;
#if !defined(OS_ANDROID)
// TODO(https://crbug.com/873320): Add support for Android.
AudioFocusManager::GetInstance()->RemoveObserver(this);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
binding_.Close();
AudioFocusManager::GetInstance()->RemoveObserver(observer_id_.value());
#endif
observer_id_.reset();
}
AudioFocusObserver::~AudioFocusObserver() = default;
} // namespace content
......@@ -6,33 +6,39 @@
#define CONTENT_BROWSER_MEDIA_SESSION_AUDIO_FOCUS_OBSERVER_H_
#include "base/macros.h"
#include "base/optional.h"
#include "content/common/content_export.h"
namespace media_session {
namespace mojom {
enum class AudioFocusType;
} // namespace mojom
} // namespace media_session
#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"
namespace content {
class MediaSession;
// The observer for observing audio focus events. This will not work on Android
// as it does not use the internal AudioFocusManager implementation.
class CONTENT_EXPORT AudioFocusObserver {
class CONTENT_EXPORT AudioFocusObserver
: public media_session::mojom::AudioFocusObserver {
public:
AudioFocusObserver();
~AudioFocusObserver();
~AudioFocusObserver() override;
// The given media session gained audio focus with the specified type.
void OnFocusGained(::media_session::mojom::MediaSessionPtr,
media_session::mojom::AudioFocusType) override {}
// The given |MediaSession| gained audio focus with the specified type.
virtual void OnFocusGained(MediaSession*,
media_session::mojom::AudioFocusType) = 0;
// The given media session lost audio focus.
void OnFocusLost(::media_session::mojom::MediaSessionPtr) override {}
// The given |NediaSession| lost audio focus.
virtual void OnFocusLost(MediaSession*) = 0;
protected:
// Called by subclasses to (un-)register the observer with AudioFocusManager.
void RegisterAudioFocusObserver();
void UnregisterAudioFocusObserver();
private:
base::Optional<mojo::InterfacePtrSetElementId> observer_id_;
mojo::Binding<media_session::mojom::AudioFocusObserver> binding_;
DISALLOW_COPY_AND_ASSIGN(AudioFocusObserver);
};
......
......@@ -5,6 +5,7 @@
#include "content/browser/media/session/media_session_impl.h"
#include <algorithm>
#include <utility>
#include "base/numerics/ranges.h"
#include "base/strings/string_util.h"
......@@ -628,6 +629,11 @@ const MediaSessionImpl::DebugInfo MediaSessionImpl::GetDebugInfo() {
return debug_info;
}
void MediaSessionImpl::BindToMojoRequest(
mojo::InterfaceRequest<media_session::mojom::MediaSession> request) {
bindings_.AddBinding(this, std::move(request));
}
void MediaSessionImpl::AbandonSystemAudioFocusIfNeeded() {
if (audio_focus_state_ == State::INACTIVE || !normal_players_.empty() ||
!pepper_players_.empty() || !one_shot_players_.empty()) {
......
......@@ -23,6 +23,9 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_contents_user_data.h"
#include "content/public/common/media_metadata.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
#if defined(OS_ANDROID)
#include "base/android/scoped_java_ref.h"
......@@ -223,6 +226,10 @@ class MediaSessionImpl : public MediaSession,
};
const DebugInfo GetDebugInfo();
// Creates a binding between |this| and |request|.
void BindToMojoRequest(
mojo::InterfaceRequest<media_session::mojom::MediaSession> request);
private:
friend class content::WebContentsUserData<MediaSessionImpl>;
friend class ::MediaSessionImplBrowserTest;
......@@ -345,6 +352,9 @@ class MediaSessionImpl : public MediaSession,
// The currently routed service (non-owned pointer).
MediaSessionServiceImpl* routed_service_;
// Bindings for Mojo pointers to |this| held by media route providers.
mojo::BindingSet<media_session::mojom::MediaSession> bindings_;
DISALLOW_COPY_AND_ASSIGN(MediaSessionImpl);
};
......
......@@ -337,6 +337,7 @@ jumbo_source_set("browser_sources") {
"//ipc",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//services/media_session/public/mojom",
"//services/network/public/mojom",
"//services/resource_coordinator/public/cpp:resource_coordinator_cpp",
"//services/service_manager/public/cpp",
......
......@@ -7,6 +7,7 @@ include_rules = [
"+device/usb/public/mojom",
"+device/fido",
"+services/device/public",
"+services/media_session/public",
"+services/network/public/cpp",
"+services/service_manager/sandbox",
"+services/resource_coordinator/public",
......
......@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h"
namespace blink {
namespace mojom {
......@@ -25,7 +26,7 @@ class WebContents;
//
// MediaSession allows clients to observe its changes via MediaSessionObserver,
// and allows clients to resume/suspend/stop the managed players.
class MediaSession {
class MediaSession : public media_session::mojom::MediaSession {
public:
enum class SuspendType {
// Suspended by the system because a transient sound needs to be played.
......@@ -40,7 +41,7 @@ class MediaSession {
// none is currently available.
CONTENT_EXPORT static MediaSession* Get(WebContents* contents);
virtual ~MediaSession() = default;
~MediaSession() override = default;
// Resume the media session.
// |type| represents the origin of the request.
......
......@@ -10,6 +10,7 @@ mojom_component("mojom") {
sources = [
"audio_focus.mojom",
"media_session.mojom",
]
public_deps = [
......
......@@ -4,6 +4,8 @@
module media_session.mojom;
import "services/media_session/public/mojom/media_session.mojom";
// These are the different types of audio focus that can be requested.
enum AudioFocusType {
// Request permanent audio focus when you plan to play audio for the
......@@ -15,3 +17,12 @@ enum AudioFocusType {
// short time and you expect the previous holder to pause playing.
kGainTransientMayDuck,
};
// The observer for audio focus events.
interface AudioFocusObserver {
// The given |session| gained audio focus with the specified |type|.
OnFocusGained(MediaSession session, AudioFocusType type);
// The given |session| lost audio focus.
OnFocusLost(MediaSession session);
};
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module media_session.mojom;
// A MediaSession manages the media session and audio focus for a given
// WebContents or ARC app.
// TODO(https://crbug.com/875004): migrate media session from content/public
// to mojo.
interface MediaSession {};
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