#include "chrome/browser/ui/global_media_controls/media_notification_service.h"
#include <memory>
#include "base/callback_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/ranges/algorithm.h"
#include "base/unguessable_token.h"
#include "chrome/browser/feature_engagement/tracker_factory.h"
#include "chrome/browser/media/router/media_router_feature.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/global_media_controls/cast_device_list_host.h"
#include "chrome/browser/ui/global_media_controls/media_notification_device_provider_impl.h"
#include "chrome/browser/ui/global_media_controls/presentation_request_notification_producer.h"
#include "chrome/browser/ui/media_router/cast_dialog_controller.h"
#include "chrome/browser/ui/media_router/media_router_ui.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "components/feature_engagement/public/tracker.h"
#include "components/global_media_controls/public/media_dialog_delegate.h"
#include "components/global_media_controls/public/media_item_manager.h"
#include "components/global_media_controls/public/media_item_producer.h"
#include "components/media_message_center/media_notification_item.h"
#include "components/media_router/browser/media_router_factory.h"
#include "components/media_router/browser/presentation/start_presentation_context.h"
#include "components/media_router/browser/presentation/web_contents_presentation_manager.h"
#include "components/sessions/content/session_tab_helper.h"
#include "content/public/browser/audio_service.h"
#include "content/public/browser/media_session.h"
#include "content/public/browser/media_session_service.h"
#include "media/base/media_switches.h"
#include "media/remoting/device_capability_checker.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/media_session/public/mojom/media_session.mojom.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/crosapi/crosapi_ash.h"
#include "chrome/browser/ash/crosapi/crosapi_manager.h"
#include "chrome/browser/ash/crosapi/media_ui_ash.h"
#elif BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/crosapi/mojom/media_ui.mojom.h"
#include "chromeos/lacros/lacros_service.h"
#endif
namespace mojom {
DeviceListClient;
DeviceListHost;
}
namespace {
constexpr int kMaxActionsRecordedToUKM = …;
void CancelRequest(
std::unique_ptr<media_router::StartPresentationContext> context,
const std::string& message) { … }
bool IsWebContentsFocused(content::WebContents* web_contents) { … }
#if BUILDFLAG(IS_CHROMEOS)
crosapi::mojom::MediaUI* GetMediaUI() {
#if BUILDFLAG(IS_CHROMEOS_ASH)
if (crosapi::CrosapiManager::IsInitialized()) {
return crosapi::CrosapiManager::Get()->crosapi_ash()->media_ui_ash();
}
#elif BUILDFLAG(IS_CHROMEOS_LACROS)
if (chromeos::LacrosService::Get()->IsAvailable<crosapi::mojom::MediaUI>()) {
return chromeos::LacrosService::Get()
->GetRemote<crosapi::mojom::MediaUI>()
.get();
}
#endif
return nullptr;
}
#endif
bool ShouldInitializeWithRemotePlaybackSource(
content::WebContents* web_contents,
media_session::mojom::RemotePlaybackMetadataPtr remote_playback_metadata) { … }
}
MediaNotificationService::MediaNotificationService(Profile* profile,
bool show_from_all_profiles)
: … { … }
#if BUILDFLAG(IS_CHROMEOS)
void MediaNotificationService::ShowDialogAsh(
std::unique_ptr<media_router::StartPresentationContext> context) {
auto* web_contents = content::WebContents::FromRenderFrameHost(
content::RenderFrameHost::FromID(
context->presentation_request().render_frame_host_id));
OnStartPresentationContextCreated(std::move(context));
auto routes = media_router::WebContentsPresentationManager::Get(web_contents)
->GetMediaRoutes();
std::string item_id;
if (routes.empty()) {
item_id = content::MediaSession::GetRequestIdFromWebContents(web_contents)
.ToString();
}
if (GetMediaUI()) {
GetMediaUI()->ShowDevicePicker(item_id);
}
}
#endif
MediaNotificationService::~MediaNotificationService() { … }
void MediaNotificationService::Shutdown() { … }
void MediaNotificationService::OnAudioSinkChosen(const std::string& item_id,
const std::string& sink_id) { … }
base::CallbackListSubscription
MediaNotificationService::RegisterAudioOutputDeviceDescriptionsCallback(
MediaNotificationDeviceProvider::GetOutputDevicesCallback callback) { … }
base::CallbackListSubscription
MediaNotificationService::RegisterIsAudioOutputDeviceSwitchingSupportedCallback(
const std::string& id,
base::RepeatingCallback<void(bool)> callback) { … }
void MediaNotificationService::OnMediaRemotingRequested(
const std::string& item_id) { … }
void MediaNotificationService::OnSinksDiscovered(const std::string& item_id) { … }
void MediaNotificationService::OnMediaSessionActionButtonPressed(
const std::string& id,
media_session::mojom::MediaSessionAction action) { … }
void MediaNotificationService::SetDialogDelegateForWebContents(
global_media_controls::MediaDialogDelegate* delegate,
content::WebContents* contents) { … }
bool MediaNotificationService::HasActiveNotificationsForWebContents(
content::WebContents* web_contents) const { … }
bool MediaNotificationService::HasLocalCastNotifications() const { … }
void MediaNotificationService::OnStartPresentationContextCreated(
std::unique_ptr<media_router::StartPresentationContext> context) { … }
void MediaNotificationService::GetDeviceListHostForSession(
const std::string& session_id,
mojo::PendingReceiver<mojom::DeviceListHost> host_receiver,
mojo::PendingRemote<mojom::DeviceListClient> client_remote) { … }
void MediaNotificationService::GetDeviceListHostForPresentation(
mojo::PendingReceiver<mojom::DeviceListHost> host_receiver,
mojo::PendingRemote<mojom::DeviceListClient> client_remote) { … }
void MediaNotificationService::SetDevicePickerProvider(
mojo::PendingRemote<global_media_controls::mojom::DevicePickerProvider>
provider_remote) { … }
std::unique_ptr<media_router::CastDialogController>
MediaNotificationService::CreateCastDialogControllerForSession(
const std::string& id) { … }
std::unique_ptr<media_router::CastDialogController>
MediaNotificationService::CreateCastDialogControllerForPresentationRequest() { … }
void MediaNotificationService::CreateCastDeviceListHost(
std::unique_ptr<media_router::CastDialogController> dialog_controller,
mojo::PendingReceiver<mojom::DeviceListHost> host_pending_receiver,
mojo::PendingRemote<mojom::DeviceListClient> client_remote,
std::optional<std::string> remoting_session_id) { … }
void MediaNotificationService::set_device_provider_for_testing(
std::unique_ptr<MediaNotificationDeviceProvider> device_provider) { … }
bool MediaNotificationService::HasCastNotificationsForWebContents(
content::WebContents* web_contents) const { … }
bool MediaNotificationService::HasTabMirroringSessionForWebContents(
content::WebContents* web_contents) const { … }
bool MediaNotificationService::HasActiveControllableSessionForWebContents(
content::WebContents* web_contents) const { … }
std::string
MediaNotificationService::GetActiveControllableSessionForWebContents(
content::WebContents* web_contents) const { … }
void MediaNotificationService::RemoveDeviceListHost(int host_id) { … }