blob: b29be3e940e33543faf239c62df67192d3a067e1 [file] [log] [blame]
// Copyright 2019 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.
#ifndef CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_SERVICE_H_
#define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_SERVICE_H_
#include <map>
#include <string>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "chrome/browser/ui/global_media_controls/cast_media_notification_producer.h"
#include "chrome/browser/ui/global_media_controls/media_notification_container_observer.h"
#include "chrome/browser/ui/global_media_controls/media_notification_device_provider.h"
#include "chrome/browser/ui/global_media_controls/media_notification_producer.h"
#include "chrome/browser/ui/global_media_controls/overlay_media_notifications_manager_impl.h"
#include "chrome/browser/ui/global_media_controls/presentation_request_notification_producer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/media_message_center/media_notification_controller.h"
#include "components/media_router/browser/presentation/web_contents_presentation_manager.h"
#include "content/public/browser/web_contents_observer.h"
#include "media/audio/audio_device_description.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/media_session/public/mojom/media_controller.mojom-forward.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
namespace content {
class StartPresentationContext;
class WebContents;
} // namespace content
namespace media_router {
class CastDialogController;
}
class MediaDialogDelegate;
class MediaNotificationServiceObserver;
class MediaSessionNotificationProducer;
class MediaNotificationService
: public KeyedService,
public media_message_center::MediaNotificationController {
public:
MediaNotificationService(Profile* profile, bool show_from_all_profiles);
MediaNotificationService(const MediaNotificationService&) = delete;
MediaNotificationService& operator=(const MediaNotificationService&) = delete;
~MediaNotificationService() override;
void AddObserver(MediaNotificationServiceObserver* observer);
void RemoveObserver(MediaNotificationServiceObserver* observer);
// media_message_center::MediaNotificationController implementation.
void ShowNotification(const std::string& id) override;
void HideNotification(const std::string& id) override;
void RemoveItem(const std::string& id) override;
scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() const override;
void LogMediaSessionActionButtonPressed(
const std::string& id,
media_session::mojom::MediaSessionAction action) override;
// KeyedService implementation.
void Shutdown() override;
// Called by the |overlay_media_notifications_manager_| when an overlay
// notification is closed.
void OnOverlayNotificationClosed(const std::string& id);
void OnCastNotificationsChanged();
// Called if the dialog is opened from the toolbar button. It shows all active
// and controllable media notifications.
void SetDialogDelegate(MediaDialogDelegate* delegate);
// Called if the dialog is opened for a presentation request from |contents|.
// It only shows media session notifications from |contents|.
void SetDialogDelegateForWebContents(MediaDialogDelegate* delegate,
content::WebContents* contents);
// Returns active controllable notifications gathered from all the
// notification producers. If empty, then there's nothing to show in the
// dialog and we can hide the toolbar icon.
std::set<std::string> GetActiveControllableNotificationIds() const;
// True if there are active non-frozen media session notifications or active
// cast notifications.
bool HasActiveNotifications() const;
// True if there are active non-frozen media session notifications or active
// cast notifications associated with |web_contents|.
bool HasActiveNotificationsForWebContents(
content::WebContents* web_contents) const;
// True if there are active frozen media session notifications.
bool HasFrozenNotifications() const;
// True if there is an open MediaDialogView associated with this service.
bool HasOpenDialog() const;
void HideMediaDialog();
std::unique_ptr<OverlayMediaNotification> PopOutNotification(
const std::string& id,
gfx::Rect bounds);
// Used by a |MediaNotificationDeviceSelectorView| to query the system
// for connected audio output devices.
base::CallbackListSubscription RegisterAudioOutputDeviceDescriptionsCallback(
MediaNotificationDeviceProvider::GetOutputDevicesCallback callback);
// Used by a |MediaNotificationAudioDeviceSelectorView| to become notified of
// audio device switching capabilities. The callback will be immediately run
// with the current availability.
base::CallbackListSubscription
RegisterIsAudioOutputDeviceSwitchingSupportedCallback(
const std::string& id,
base::RepeatingCallback<void(bool)> callback);
void OnPresentationRequestCreated(
std::unique_ptr<media_router::StartPresentationContext> context);
void OnStartPresentationContextCreated(
std::unique_ptr<media_router::StartPresentationContext> context);
// Instantiates a MediaRouterViewsUI object associated with the Session with
// the given |session_id|.
std::unique_ptr<media_router::CastDialogController>
CreateCastDialogControllerForSession(const std::string& session_id);
// Instantiates a MediaRouterViewsUI object associated with the
// PresentationRequest that |presentation_request_notification_producer_|
// manages.
std::unique_ptr<media_router::CastDialogController>
CreateCastDialogControllerForPresentationRequest();
void ShowAndObserveContainer(const std::string& id);
private:
// TODO(crbug.com/1021643): Remove this friend declaration once the Session
// class is moved to MediaSessionNotificationProducer.
friend class MediaSessionNotificationProducer;
friend class MediaNotificationProviderImplTest;
friend class MediaNotificationServiceTest;
friend class MediaNotificationServiceCastTest;
friend class MediaToolbarButtonControllerTest;
friend class PresentationRequestNotificationProducerTest;
FRIEND_TEST_ALL_PREFIXES(MediaNotificationServiceTest,
HideAfterTimeoutAndActiveAgainOnPlay);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationServiceTest,
SessionIsRemovedImmediatelyWhenATabCloses);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationServiceTest, DismissesMediaSession);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationServiceTest,
HidesInactiveNotifications);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationServiceTest,
HidingNotification_FeatureDisabled);
FRIEND_TEST_ALL_PREFIXES(MediaNotificationServiceCastTest,
ShowSupplementalNotifications);
// Looks up a notification from any source. Returns null if not found.
base::WeakPtr<media_message_center::MediaNotificationItem>
GetNotificationItem(const std::string& id);
// Called after changing anything about a notification to notify any observers
// and update the visibility of supplemental notifications.
void OnNotificationChanged();
MediaNotificationProducer* GetNotificationProducer(
const std::string& notification_id);
// Updates |dialog_delegate_| and notifies |observers_|. Called from
// SetDialogDelegate() and SetDialogDelegateForPresentationRequest().
void SetDialogDelegateCommon(MediaDialogDelegate* delegate);
// True if there is an open MediaDialogView and the dialog is opened for a
// PresentationRequest.
bool HasOpenDialogForPresentationRequest() const;
MediaDialogDelegate* dialog_delegate_ = nullptr;
// True if the dialog was opened by |SetDialogDelegateForWebContents()|. The
// value does not indicate whether the MediaDialogView is opened or not.
bool dialog_opened_from_presentation_ = false;
std::unique_ptr<MediaSessionNotificationProducer>
media_session_notification_producer_;
std::unique_ptr<CastMediaNotificationProducer> cast_notification_producer_;
std::unique_ptr<PresentationRequestNotificationProducer>
presentation_request_notification_producer_;
// Pointers to all notification producers owned by |this|.
std::set<MediaNotificationProducer*> notification_producers_;
base::ObserverList<MediaNotificationServiceObserver> observers_;
base::WeakPtrFactory<MediaNotificationService> weak_ptr_factory_{this};
};
#endif // CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_SERVICE_H_