Commit ddb531f7 authored by Becca Hughes's avatar Becca Hughes Committed by Commit Bot

[Media Session] Fix for Lacros

At the moment in Lacros there are two instances of the
Media Session Service (MSS) one hosted in ash-chrome and
the other in lacros-chrome. This means that sessions in
either browser process cannot see sessions from the other.

This changes it so when a client asks for lacros-chrome
MSS instead of providing a locally hosted MSS it binds
the MSS in ash-chrome.

BUG=1140215

Change-Id: Ic155a6cd928f0735095f849f309f9075dbb1d36f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2485850Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarErik Chen <erikchen@chromium.org>
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825016}
parent 324bc488
......@@ -32,6 +32,7 @@
#include "chromeos/crosapi/mojom/select_file.mojom.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/device_service.h"
#include "content/public/browser/media_session_service.h"
namespace crosapi {
......@@ -114,6 +115,25 @@ void AshChromeServiceImpl::BindFeedback(
feedback_ash_ = std::make_unique<FeedbackAsh>(std::move(receiver));
}
void AshChromeServiceImpl::BindMediaSessionController(
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
receiver) {
content::GetMediaSessionService().BindMediaControllerManager(
std::move(receiver));
}
void AshChromeServiceImpl::BindMediaSessionAudioFocus(
mojo::PendingReceiver<media_session::mojom::AudioFocusManager> receiver) {
content::GetMediaSessionService().BindAudioFocusManager(std::move(receiver));
}
void AshChromeServiceImpl::BindMediaSessionAudioFocusDebug(
mojo::PendingReceiver<media_session::mojom::AudioFocusManagerDebug>
receiver) {
content::GetMediaSessionService().BindAudioFocusManagerDebug(
std::move(receiver));
}
void AshChromeServiceImpl::OnLacrosStartup(mojom::LacrosInfoPtr lacros_info) {
BrowserManager::Get()->set_lacros_version(lacros_info->lacros_version);
}
......
......@@ -46,6 +46,15 @@ class AshChromeServiceImpl : public mojom::AshChromeService {
mojo::PendingReceiver<device::mojom::HidManager> receiver) override;
void BindFeedback(mojo::PendingReceiver<mojom::Feedback> receiver) override;
void OnLacrosStartup(mojom::LacrosInfoPtr lacros_info) override;
void BindMediaSessionController(
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
receiver) override;
void BindMediaSessionAudioFocus(
mojo::PendingReceiver<media_session::mojom::AudioFocusManager> receiver)
override;
void BindMediaSessionAudioFocusDebug(
mojo::PendingReceiver<media_session::mojom::AudioFocusManagerDebug>
receiver) override;
private:
mojo::Receiver<mojom::AshChromeService> receiver_;
......
......@@ -149,7 +149,7 @@ bool IsLacrosWindow(const aura::Window* window) {
base::flat_map<base::Token, uint32_t> GetInterfaceVersions() {
static_assert(
crosapi::mojom::AshChromeService::Version_ == 5,
crosapi::mojom::AshChromeService::Version_ == 6,
"if you add a new crosapi, please add it to the version map here");
InterfaceVersions versions;
AddVersion<crosapi::mojom::AccountManager>(&versions);
......@@ -162,6 +162,9 @@ base::flat_map<base::Token, uint32_t> GetInterfaceVersions() {
AddVersion<crosapi::mojom::SnapshotCapturer>(&versions);
AddVersion<device::mojom::HidConnection>(&versions);
AddVersion<device::mojom::HidManager>(&versions);
AddVersion<media_session::mojom::MediaControllerManager>(&versions);
AddVersion<media_session::mojom::AudioFocusManager>(&versions);
AddVersion<media_session::mojom::AudioFocusManagerDebug>(&versions);
return versions;
}
......
// Copyright 2020 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.
#include "chrome/browser/ui/browser.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/media_session.h"
#include "content/public/test/browser_test.h"
#include "services/media_session/public/cpp/test/mock_media_session.h"
class MediaSessionLacrosBrowserTest : public InProcessBrowserTest {
protected:
MediaSessionLacrosBrowserTest() = default;
MediaSessionLacrosBrowserTest(const MediaSessionLacrosBrowserTest&) = delete;
MediaSessionLacrosBrowserTest& operator=(
const MediaSessionLacrosBrowserTest&) = delete;
~MediaSessionLacrosBrowserTest() override = default;
};
// This test checks that a Media Session can become active which can only
// happen if the Media Session Service is working correctly.
IN_PROC_BROWSER_TEST_F(MediaSessionLacrosBrowserTest, CheckServiceWorks) {
ASSERT_TRUE(embedded_test_server()->Start());
// Navigate to a test page with some media on it.
ui_test_utils::NavigateToURL(
browser(), embedded_test_server()->GetURL("/media/autoplay_iframe.html"));
auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents();
media_session::test::MockMediaSessionMojoObserver observer(
*content::MediaSession::Get(web_contents));
// Start playback.
ASSERT_EQ(
nullptr,
content::EvalJs(web_contents, "document.getElementById('video').play()"));
// Wait for the session to become active.
observer.WaitForState(
media_session::mojom::MediaSessionInfo::SessionState::kActive);
}
......@@ -8,6 +8,7 @@
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/media/router/chrome_media_router_factory.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/global_media_controls/media_toolbar_button_observer.h"
......@@ -35,6 +36,9 @@
using media_session::mojom::MediaSessionAction;
// Global Media Controls are not supported on Chrome OS.
#if !BUILDFLAG(IS_LACROS)
namespace {
class MediaToolbarButtonWatcher : public MediaToolbarButtonObserver,
......@@ -894,3 +898,5 @@ IN_PROC_BROWSER_TEST_F(MediaDialogViewBrowserTest, LiveCaption) {
EXPECT_FALSE(
browser()->profile()->GetPrefs()->GetBoolean(prefs::kLiveCaptionEnabled));
}
#endif // !BUILDFLAG(IS_LACROS)
......@@ -3177,6 +3177,7 @@ if (chromeos_is_browser_only) {
sources = [
"../browser/lacros/file_manager_lacros_browsertest.cc",
"../browser/lacros/keystore_service_lacros_browsertest.cc",
"../browser/lacros/media_session_lacros_browsertest.cc",
"../browser/lacros/message_center_lacros_browsertest.cc",
"../browser/lacros/screen_manager_lacros_browsertest.cc",
]
......@@ -3186,6 +3187,8 @@ if (chromeos_is_browser_only) {
":test_support",
]
data = [ "data/media/" ]
data_deps = [ "//chrome:packed_resources" ]
}
}
......
......@@ -39,6 +39,7 @@ mojom("mojom") {
public_deps = [
"//mojo/public/mojom/base",
"//services/device/public/mojom:mojom",
"//services/media_session/public/mojom:mojom",
"//ui/gfx/image/mojom",
"//url/mojom:url_mojom_gurl",
]
......
......@@ -15,6 +15,8 @@ import "mojo/public/mojom/base/big_string.mojom";
import "mojo/public/mojom/base/token.mojom";
import "mojo/public/mojom/base/values.mojom";
import "services/device/public/mojom/hid.mojom";
import "services/media_session/public/mojom/audio_focus.mojom";
import "services/media_session/public/mojom/media_controller.mojom";
import "url/mojom/url.mojom";
// LacrosInfo is a set of parameters passed to ash from lacros-chrome
......@@ -36,8 +38,8 @@ struct LacrosInfo {
// milestone when you added it, to help us reason about compatibility between
// lacros-chrome and older ash-chrome binaries.
//
// Next version: 6
// Next method id: 9
// Next version: 7
// Next method id: 12
[Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e"]
interface AshChromeService {
// Binds Chrome OS Account Manager for Identity management.
......@@ -75,6 +77,24 @@ interface AshChromeService {
// Added in M87.
[MinVersion=3] BindFeedback@5(pending_receiver<Feedback> receiver);
// Binds the Media Session service (controller) for enabling media playback
// control.
// Added in M88.
[MinVersion=6] BindMediaSessionController@9(
pending_receiver<media_session.mojom.MediaControllerManager> receiver);
// Binds the Media Session service (audio focus) for enabling media sessions
// to register with the service so they can be controlled.
// Added in M88.
[MinVersion=6] BindMediaSessionAudioFocus@10(
pending_receiver<media_session.mojom.AudioFocusManager> receiver);
// Binds the Media Session service (audio focus debug) for enabling debugging
// of media playback sessions.
// Added in M88.
[MinVersion=6] BindMediaSessionAudioFocusDebug@11(
pending_receiver<media_session.mojom.AudioFocusManagerDebug> receiver);
// Passes generic lacros information such as lacros version, etc into ash
// in |lacros_info| during startup.
// Added in M87.
......
......@@ -180,6 +180,30 @@ class LacrosChromeServiceNeverBlockingState
ash_chrome_service_->BindFileManager(std::move(pending_receiver));
}
void BindMediaSessionAudioFocusReceiver(
mojo::PendingReceiver<media_session::mojom::AudioFocusManager>
pending_receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ash_chrome_service_->BindMediaSessionAudioFocus(
std::move(pending_receiver));
}
void BindMediaSessionAudioFocusDebugReceiver(
mojo::PendingReceiver<media_session::mojom::AudioFocusManagerDebug>
pending_receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ash_chrome_service_->BindMediaSessionAudioFocusDebug(
std::move(pending_receiver));
}
void BindMediaSessionControllerReceiver(
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
pending_receiver) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ash_chrome_service_->BindMediaSessionController(
std::move(pending_receiver));
}
base::WeakPtr<LacrosChromeServiceNeverBlockingState> GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
......@@ -397,6 +421,53 @@ bool LacrosChromeServiceImpl::IsScreenManagerAvailable() {
return AshChromeServiceVersion() >= 0;
}
bool LacrosChromeServiceImpl::IsMediaSessionAudioFocusAvailable() {
return AshChromeServiceVersion() >= 6;
}
void LacrosChromeServiceImpl::BindAudioFocusManager(
mojo::PendingReceiver<media_session::mojom::AudioFocusManager> remote) {
DCHECK_CALLED_ON_VALID_SEQUENCE(affine_sequence_checker_);
DCHECK(IsMediaSessionAudioFocusAvailable());
never_blocking_sequence_->PostTask(
FROM_HERE, base::BindOnce(&LacrosChromeServiceNeverBlockingState::
BindMediaSessionAudioFocusReceiver,
weak_sequenced_state_, std::move(remote)));
}
bool LacrosChromeServiceImpl::IsMediaSessionAudioFocusDebugAvailable() {
return AshChromeServiceVersion() >= 6;
}
void LacrosChromeServiceImpl::BindAudioFocusManagerDebug(
mojo::PendingReceiver<media_session::mojom::AudioFocusManagerDebug>
remote) {
DCHECK_CALLED_ON_VALID_SEQUENCE(affine_sequence_checker_);
DCHECK(IsMediaSessionAudioFocusAvailable());
never_blocking_sequence_->PostTask(
FROM_HERE, base::BindOnce(&LacrosChromeServiceNeverBlockingState::
BindMediaSessionAudioFocusDebugReceiver,
weak_sequenced_state_, std::move(remote)));
}
bool LacrosChromeServiceImpl::IsMediaSessionControllerAvailable() {
return AshChromeServiceVersion() >= 6;
}
void LacrosChromeServiceImpl::BindMediaControllerManager(
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
remote) {
DCHECK_CALLED_ON_VALID_SEQUENCE(affine_sequence_checker_);
DCHECK(IsMediaSessionAudioFocusAvailable());
never_blocking_sequence_->PostTask(
FROM_HERE, base::BindOnce(&LacrosChromeServiceNeverBlockingState::
BindMediaSessionControllerReceiver,
weak_sequenced_state_, std::move(remote)));
}
bool LacrosChromeServiceImpl::IsOnLacrosStartupAvailable() {
return AshChromeServiceVersion() >= 3;
}
......
......@@ -135,6 +135,32 @@ class COMPONENT_EXPORT(CHROMEOS_LACROS) LacrosChromeServiceImpl {
return feedback_remote_;
}
// media_session_audio_focus_remote() can only be used when this method
// returns true;
bool IsMediaSessionAudioFocusAvailable();
// This must be called on the affine sequence.
void BindAudioFocusManager(
mojo::PendingReceiver<media_session::mojom::AudioFocusManager> remote);
// media_session_audio_focus_debug_remote() can only be used when this method
// returns true;
bool IsMediaSessionAudioFocusDebugAvailable();
// This must be called on the affine sequence.
void BindAudioFocusManagerDebug(
mojo::PendingReceiver<media_session::mojom::AudioFocusManagerDebug>
remote);
// media_session_controller_remote() can only be used when this method returns
// true;
bool IsMediaSessionControllerAvailable();
// This must be called on the affine sequence.
void BindMediaControllerManager(
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
remote);
// account_manager_remote() can only be used if this method returns true.
bool IsAccountManagerAvailable();
......
......@@ -7,18 +7,75 @@
#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/threading/sequence_local_storage_slot.h"
#include "build/chromeos_buildflags.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/media_session/media_session_service_impl.h"
#include "services/media_session/public/cpp/features.h"
#if BUILDFLAG(IS_LACROS)
#include "chromeos/lacros/lacros_chrome_service_impl.h"
#include "services/media_session/public/cpp/media_session_service.h"
#endif // BUILDFLAG(IS_LACROS)
namespace content {
#if BUILDFLAG(IS_LACROS)
namespace {
class LacrosMediaSessionServiceImpl
: public media_session::MediaSessionService {
public:
LacrosMediaSessionServiceImpl() = default;
~LacrosMediaSessionServiceImpl() override = default;
LacrosMediaSessionServiceImpl(const LacrosMediaSessionServiceImpl&) = delete;
LacrosMediaSessionServiceImpl& operator=(
const LacrosMediaSessionServiceImpl&) = delete;
void BindAudioFocusManager(
mojo::PendingReceiver<media_session::mojom::AudioFocusManager> receiver)
override {
auto* lacros_chrome_service = chromeos::LacrosChromeServiceImpl::Get();
if (lacros_chrome_service &&
lacros_chrome_service->IsMediaSessionAudioFocusAvailable()) {
lacros_chrome_service->BindAudioFocusManager(std::move(receiver));
}
}
void BindAudioFocusManagerDebug(
mojo::PendingReceiver<media_session::mojom::AudioFocusManagerDebug>
receiver) override {
auto* lacros_chrome_service = chromeos::LacrosChromeServiceImpl::Get();
if (lacros_chrome_service &&
lacros_chrome_service->IsMediaSessionAudioFocusDebugAvailable()) {
lacros_chrome_service->BindAudioFocusManagerDebug(std::move(receiver));
}
}
void BindMediaControllerManager(
mojo::PendingReceiver<media_session::mojom::MediaControllerManager>
receiver) override {
auto* lacros_chrome_service = chromeos::LacrosChromeServiceImpl::Get();
if (lacros_chrome_service &&
lacros_chrome_service->IsMediaSessionControllerAvailable()) {
lacros_chrome_service->BindMediaControllerManager(std::move(receiver));
}
}
};
} // namespace
#endif // BUILDFLAG(IS_LACROS)
media_session::MediaSessionService& GetMediaSessionService() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
#if BUILDFLAG(IS_LACROS)
static base::NoDestructor<LacrosMediaSessionServiceImpl> service;
return *service;
#else
static base::NoDestructor<media_session::MediaSessionServiceImpl> service;
return *service;
#endif
}
} // namespace content
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "content/public/browser/media_keys_listener_manager.h"
#include "build/chromeos_buildflags.h"
#if !defined(OS_CHROMEOS)
#include "base/feature_list.h"
......@@ -13,7 +14,7 @@ namespace content {
// static
bool MediaKeysListenerManager::IsMediaKeysListenerManagerEnabled() {
#if defined(OS_CHROMEOS)
#if defined(OS_CHROMEOS) || BUILDFLAG(IS_LACROS)
return false;
#else
return base::FeatureList::IsEnabled(media::kHardwareMediaKeyHandling);
......
......@@ -5,6 +5,7 @@
module mojo_base.mojom;
// Corresponds to |base::UnguessableToken| in base/unguessable_token.h
[Stable]
struct UnguessableToken {
uint64 high;
uint64 low;
......
......@@ -10,7 +10,7 @@ import "services/media_session/public/mojom/media_session.mojom";
// Next MinVersion: 8
// These are the different modes the AudioFocusManager can enforce audio focus.
[Extensible]
[Stable, Extensible]
enum EnforcementMode {
// This will default to whatever enforcement mode is configured through
// feature flags.
......@@ -32,7 +32,7 @@ enum EnforcementMode {
};
// These are the different types of audio focus that can be requested.
[Extensible]
[Stable, Extensible]
enum AudioFocusType {
// Request permanent audio focus when you plan to play audio for the
// foreseeable future (for example, when playing music) and you expect the
......@@ -55,6 +55,7 @@ enum AudioFocusType {
// Contains information about |MediaSessions| that have requested audio focus
// and their current requested type.
[Stable]
struct AudioFocusRequestState {
MediaSessionInfo session_info;
AudioFocusType audio_focus_type;
......@@ -64,17 +65,20 @@ struct AudioFocusRequestState {
};
// The observer for audio focus events.
// Next method id: 2
[Stable]
interface AudioFocusObserver {
// The given |session| gained audio focus.
OnFocusGained(AudioFocusRequestState state);
OnFocusGained@0(AudioFocusRequestState state);
// The given |session| lost audio focus.
OnFocusLost(AudioFocusRequestState state);
OnFocusLost@1(AudioFocusRequestState state);
};
// Controls audio focus for an associated request.
// Next Method ID: 5
// Deprecated method IDs: 3, 4
[Stable]
interface AudioFocusRequestClient {
// Requests updated audio focus for this request. If the request was granted
// then the callback will resolve.
......@@ -92,6 +96,7 @@ interface AudioFocusRequestClient {
// the media session service.
// Next Method ID: 9
// Deprecated method IDs: 3
[Stable, Uuid="acb554fd-5b45-4759-8e8e-ad4be348fba8"]
interface AudioFocusManager {
// Requests audio focus with |type| for the |session| with |session_info|.
// Media sessions should provide a |request| that will provide an
......@@ -152,8 +157,10 @@ interface AudioFocusManager {
};
// Provides debug information about audio focus requests.
// Next method id: 1
[Stable, Uuid="c3b8b522-9a66-49cf-881b-c5fd19391b76"]
interface AudioFocusManagerDebug {
// Gets debugging information for a |MediaSession| with |request_id|.
GetDebugInfoForRequest(mojo_base.mojom.UnguessableToken request_id)
GetDebugInfoForRequest@0(mojo_base.mojom.UnguessableToken request_id)
=> (MediaSessionDebugInfo debug_info);
};
......@@ -8,123 +8,131 @@ import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "services/media_session/public/mojom/media_session.mojom";
// Next Method ID: 3
[Stable, Uuid="1ed3225e-33c8-487b-b79f-4c3ec13ad623"]
interface MediaControllerManager {
// Creates a MediaController linked to a specific session with |request_id|.
// This should match the |request_id| from the AudioFocusRequestState.
CreateMediaControllerForSession(
CreateMediaControllerForSession@0(
pending_receiver<MediaController> receiver,
mojo_base.mojom.UnguessableToken request_id);
// Creates a MediaController linked to the active session. This will
// automatically route commands to the correct session if the active session
// changes. If there is no active session then commands will be no-ops.
CreateActiveMediaController(pending_receiver<MediaController> receiver);
CreateActiveMediaController@1(pending_receiver<MediaController> receiver);
// Suspends all media sessions.
SuspendAllSessions();
SuspendAllSessions@2();
};
// Controls a MediaSession. If the media session is not controllable then the
// commands will be no-ops.
// Next Method ID: 14
[Stable]
interface MediaController {
// Suspend the media session.
Suspend();
Suspend@0();
// Resume the media session.
Resume();
Resume@1();
// Stop the media session.
Stop();
Stop@2();
// This will either suspend or resume the media session based on the
// playback state.
ToggleSuspendResume();
ToggleSuspendResume@3();
// Adds an observer that will forward events from the active media session.
// 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(pending_remote<MediaControllerObserver> observer);
AddObserver@4(pending_remote<MediaControllerObserver> observer);
// Skip to the previous track. If there is no previous track then this will be
// a no-op.
PreviousTrack();
PreviousTrack@5();
// Skip to the next track. If there is no next track then this will be a
// no-op.
NextTrack();
NextTrack@6();
// Seek the media session. If the media cannot seek then this will be a
// no-op. The |seek_time| is the time delta that the media will seek by and
// supports both positive and negative values. This value cannot be zero.
// The |kDefaultSeekTimeSeconds| provides a default value for seeking by a
// few seconds.
Seek(mojo_base.mojom.TimeDelta seek_time);
Seek@7(mojo_base.mojom.TimeDelta seek_time);
// Creates an image observer that will be notified when the image of |type|
// for the underlying media session has changed. The image will be at least
// |minimum_size_pc| and closest to |desired_size_px|.
ObserveImages(
ObserveImages@8(
MediaSessionImageType type, int32 minimum_size_px, int32 desired_size_px,
pending_remote<MediaControllerImageObserver> observer);
// Seek the media session to a non-negative |seek_time| from the beginning of
// the current playing media. If the media cannot seek then this will be a
// no-op.
SeekTo(mojo_base.mojom.TimeDelta seek_time);
SeekTo@9(mojo_base.mojom.TimeDelta seek_time);
// Scrub ("fast seek") the media session to a non-negative |seek_time| from
// the beginning of the current playing media. If the media cannot scrub then
// this will be a no-op. The client should call |SeekTo| to finish the
// scrubbing operation.
ScrubTo(mojo_base.mojom.TimeDelta seek_time);
ScrubTo@10(mojo_base.mojom.TimeDelta seek_time);
// Enter picture-in-picture.
EnterPictureInPicture();
EnterPictureInPicture@11();
// Exit picture-in-picture.
ExitPictureInPicture();
ExitPictureInPicture@12();
// Routes the audio from this Media Session to the given output device. If
// |id| is null, we will route to the default output device.
SetAudioSinkId(string? id);
SetAudioSinkId@13(string? id);
};
// The observer for observing media controller events. This is different to a
// MediaSessionObserver because a media controller can have nullable session
// info which will be null if it is not bound to a media session. This would
// be invalid for a media session because it must always have some state.
// Next Method ID: 5
[Stable]
interface MediaControllerObserver {
// Called when the state of the bound media session changes. If |info| is
// empty then the controller is no longer bound to a media session.
MediaSessionInfoChanged(MediaSessionInfo? info);
MediaSessionInfoChanged@0(MediaSessionInfo? info);
// Called when the bound media session has changed metadata. If |metadata|
// is null then it can be reset, e.g. the media that ws being played has
// been stopped.
MediaSessionMetadataChanged(MediaMetadata? metadata);
MediaSessionMetadataChanged@1(MediaMetadata? metadata);
// Called when the bound media session action list has changed. This tells
// the observer which actions can be used to control the session.
MediaSessionActionsChanged(array<MediaSessionAction> action);
MediaSessionActionsChanged@2(array<MediaSessionAction> action);
// Called when the bound media session changes. This tells the observer the
// |request_id| of the new session of null if it is not bound to a session.
MediaSessionChanged(mojo_base.mojom.UnguessableToken? request_id);
MediaSessionChanged@3(mojo_base.mojom.UnguessableToken? request_id);
// Called when the position of the bound media session has changed. If
// |position| is empty then the media session does not have a position or
// the controller is no longer bound to a media session. Position is updated
// anytime the position state (playback rate, duration) is changed or the
// media is seeked.
MediaSessionPositionChanged(MediaPosition? position);
MediaSessionPositionChanged@4(MediaPosition? position);
};
// The observer for observing when images associated with a media controller
// change. This is a separate observer because not all clients need to handle
// images.
// Next Method ID: 1
[Stable]
interface MediaControllerImageObserver {
// Called when the observed media controller has a new image of |type|.
// It may be null if there is no image.
MediaControllerImageChanged(
MediaControllerImageChanged@0(
MediaSessionImageType type, MediaImageBitmap? bitmap);
};
......@@ -11,13 +11,13 @@ import "url/mojom/url.mojom";
// Next MinVersion: 10
[Extensible]
[Stable, Extensible]
enum MediaPlaybackState {
kPaused,
kPlaying,
};
[Extensible]
[Stable, Extensible]
enum MediaSessionAction {
kPlay,
kPause,
......@@ -34,7 +34,7 @@ enum MediaSessionAction {
kSwitchAudioDevice,
};
[Extensible]
[Stable, Extensible]
enum MediaSessionImageType {
// The artwork associated with the media session (e.g album art).
kArtwork,
......@@ -43,13 +43,13 @@ enum MediaSessionImageType {
kSourceIcon,
};
[Extensible]
[Stable, Extensible]
enum MediaPictureInPictureState {
kNotInPictureInPicture,
kInPictureInPicture,
};
[Extensible]
[Stable, Extensible]
enum MediaAudioVideoState {
kUnknown,
kAudioOnly,
......@@ -58,6 +58,7 @@ enum MediaAudioVideoState {
// Album art in MediaMetadata
// Spec: https://wicg.github.io/mediasession/
[Stable]
struct MediaImage {
url.mojom.Url src;
mojo_base.mojom.String16 type;
......@@ -65,6 +66,7 @@ struct MediaImage {
};
// MediaMetadata
[Stable]
struct MediaMetadata {
// These are defined in the spec: https://wicg.github.io/mediasession/
mojo_base.mojom.String16 title;
......@@ -78,7 +80,7 @@ struct MediaMetadata {
};
// The color type of the bitmap.
[Extensible]
[Stable, Extensible]
enum MediaImageBitmapColorType {
kRGBA_8888, // On Android, this is Bitmap.Config.ARGB_8888
kBGRA_8888,
......@@ -87,6 +89,7 @@ enum MediaImageBitmapColorType {
// A bitmap image. We use this instead of SkImage or skia.image.Bitmap so we can
// use it in ARC and we do not use ArcBitmap because we need to use it in the
// service.
[Stable]
struct MediaImageBitmap {
int32 width;
int32 height;
......@@ -94,6 +97,7 @@ struct MediaImageBitmap {
[MinVersion=5] MediaImageBitmapColorType color_type;
};
[Stable]
struct MediaPosition {
double playback_rate;
mojo_base.mojom.TimeDelta duration;
......@@ -102,8 +106,9 @@ struct MediaPosition {
};
// Contains state information about a MediaSession.
[Stable]
struct MediaSessionInfo {
[Extensible]
[Stable, Extensible]
enum SessionState {
// The MediaSession is currently playing media.
kActive,
......@@ -156,6 +161,7 @@ struct MediaSessionInfo {
// Contains debugging information about a MediaSession. This will be displayed
// on the Media Internals WebUI.
[Stable]
struct MediaSessionDebugInfo {
// A unique name for the MediaSession.
string name;
......@@ -169,6 +175,7 @@ struct MediaSessionDebugInfo {
// The observer for observing media session events.
// Next Method ID: 5
[Stable]
interface MediaSessionObserver {
// Call when the info associated with the session changed.
MediaSessionInfoChanged@0(MediaSessionInfo info);
......@@ -192,11 +199,10 @@ interface MediaSessionObserver {
// 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.
// Next Method ID: 18
[Stable]
interface MediaSession {
[Extensible]
[Stable, Extensible]
enum SuspendType {
// Suspended by the system because a transient sound needs to be played.
kSystem,
......
// 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;
import "services/media_session/public/mojom/audio_focus.mojom";
import "services/media_session/public/mojom/media_controller.mojom";
// The main interface to the Media Session service. Privileged and bound only by
// the browser process. In Lacros the service does not exist in lacros-chrome
// which will forward requests to ash-chrome which hosts the service in its
// own browser process.
// Next method id: 4
[Stable, Uuid="efd33ccb-8b58-4ddc-84a2-ba58d052979b"]
interface MediaSessionService {
// Binds an AudioFocusManager endpoint in the service.
BindAudioFocusManager@0(pending_receiver<AudioFocusManager> receiver);
// Binds an endpoint for debugging the AudioFocusManager.
BindAudioFocusManagerDebug@1(pending_receiver<AudioFocusManagerDebug> receiver);
// Binds a MediaControllerManager endpoint in the service.
BindMediaControllerManager@2(pending_receiver<MediaControllerManager> receiver);
// Binds a receiver to this service. This is used by Lacros to allow one
// browser process (lacros-chrome) to bind the entire MediaSessionService
// interface in another process (ash-chrome).
Bind@3(pending_receiver<MediaSessionService> receiver);
};
......@@ -22,6 +22,7 @@ struct Point3F {
float z;
};
[Stable]
struct Size {
int32 width;
int32 height;
......
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