Commit 91eef299 authored by Takumi Fujimoto's avatar Takumi Fujimoto Committed by Chromium LUCI CQ

Create the MediaNotificatoinProvider interface

Part 1 of MediaNotificationService refactoring. Create an interface and
make CastMediaNotificationProvider and
PresentationRequestNotificationProvider implement it.

Bug: 1021643
Change-Id: I899d0430a59a7432ed2d55bcbc23af3cb8405a07
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2606650
Commit-Queue: Takumi Fujimoto <takumif@chromium.org>
Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844342}
parent 1d302153
......@@ -994,6 +994,7 @@ static_library("ui") {
"global_media_controls/media_notification_device_provider.h",
"global_media_controls/media_notification_device_provider_impl.cc",
"global_media_controls/media_notification_device_provider_impl.h",
"global_media_controls/media_notification_producer.h",
"global_media_controls/media_notification_service.cc",
"global_media_controls/media_notification_service.h",
"global_media_controls/media_notification_service_factory.cc",
......
......@@ -54,6 +54,23 @@ CastMediaNotificationProvider::CastMediaNotificationProvider(
CastMediaNotificationProvider::~CastMediaNotificationProvider() = default;
base::WeakPtr<media_message_center::MediaNotificationItem>
CastMediaNotificationProvider::GetNotificationItem(const std::string& id) {
const auto item_it = items_.find(id);
if (item_it == items_.end())
return nullptr;
return item_it->second.GetWeakPtr();
}
std::set<std::string>
CastMediaNotificationProvider::GetActiveControllableNotificationIds() const {
std::set<std::string> ids;
for (const auto& item : items_) {
ids.insert(item.first);
}
return ids;
}
void CastMediaNotificationProvider::OnRoutesUpdated(
const std::vector<media_router::MediaRoute>& routes,
const std::vector<media_router::MediaRoute::Id>& joinable_route_ids) {
......@@ -96,14 +113,6 @@ void CastMediaNotificationProvider::OnRoutesUpdated(
items_changed_callback_.Run();
}
base::WeakPtr<media_message_center::MediaNotificationItem>
CastMediaNotificationProvider::GetNotificationItem(const std::string& id) {
const auto item_it = items_.find(id);
if (item_it == items_.end())
return nullptr;
return item_it->second.GetWeakPtr();
}
bool CastMediaNotificationProvider::HasItems() const {
return !items_.empty();
}
......
......@@ -12,6 +12,7 @@
#include "base/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/global_media_controls/cast_media_notification_item.h"
#include "chrome/browser/ui/global_media_controls/media_notification_producer.h"
#include "components/media_router/browser/media_routes_observer.h"
class Profile;
......@@ -22,7 +23,8 @@ class MediaNotificationController;
// Manages media notifications shown in the Global Media Controls dialog for
// active Cast sessions.
class CastMediaNotificationProvider : public media_router::MediaRoutesObserver {
class CastMediaNotificationProvider : public MediaNotificationProducer,
public media_router::MediaRoutesObserver {
public:
CastMediaNotificationProvider(
Profile* profile,
......@@ -40,14 +42,16 @@ class CastMediaNotificationProvider : public media_router::MediaRoutesObserver {
const CastMediaNotificationProvider&) = delete;
~CastMediaNotificationProvider() override;
// MediaNotificationProducer:
base::WeakPtr<media_message_center::MediaNotificationItem>
GetNotificationItem(const std::string& id) override;
std::set<std::string> GetActiveControllableNotificationIds() const override;
// media_router::MediaRoutesObserver:
void OnRoutesUpdated(const std::vector<media_router::MediaRoute>& routes,
const std::vector<media_router::MediaRoute::Id>&
joinable_route_ids) override;
base::WeakPtr<media_message_center::MediaNotificationItem>
GetNotificationItem(const std::string& id);
virtual bool HasItems() const;
size_t GetItemCount() const;
......
// Copyright 2021 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_PRODUCER_H_
#define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_PRODUCER_H_
#include <set>
#include <string>
#include "base/memory/weak_ptr.h"
namespace media_message_center {
class MediaNotificationItem;
} // namespace media_message_center
// Creates and owns the media notification items shown in the Global Media
// Controls. There are multiple MediaNotificationProducers for different types
// of notification items.
class MediaNotificationProducer {
public:
virtual base::WeakPtr<media_message_center::MediaNotificationItem>
GetNotificationItem(const std::string& id) = 0;
virtual std::set<std::string> GetActiveControllableNotificationIds()
const = 0;
};
#endif // CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_PRODUCER_H_
......@@ -326,10 +326,13 @@ MediaNotificationService::MediaNotificationService(Profile* profile,
base::BindRepeating(
&MediaNotificationService::OnCastNotificationsChanged,
base::Unretained(this)));
notification_providers_.insert(cast_notification_provider_.get());
}
if (media_router::GlobalMediaControlsCastStartStopEnabled()) {
presentation_request_notification_provider_ =
std::make_unique<PresentationRequestNotificationProvider>(this);
notification_providers_.insert(
presentation_request_notification_provider_.get());
}
}
......@@ -693,17 +696,18 @@ void MediaNotificationService::SetDialogDelegate(
if (!dialog_delegate_)
return;
std::list<std::string> sorted_session_ids;
for (const std::string& id : active_controllable_session_ids_) {
auto notification_ids = GetActiveControllableNotificationIds();
std::list<std::string> sorted_notification_ids;
for (const std::string& id : notification_ids) {
auto session_it = sessions_.find(id);
if (session_it != sessions_.end() && session_it->second.IsPlaying()) {
sorted_session_ids.push_front(id);
sorted_notification_ids.push_front(id);
} else {
sorted_session_ids.push_back(id);
sorted_notification_ids.push_back(id);
}
}
for (const std::string& id : sorted_session_ids) {
for (const std::string& id : sorted_notification_ids) {
base::WeakPtr<media_message_center::MediaNotificationItem> item =
GetNotificationItem(id);
MediaNotificationContainerImpl* container =
......@@ -717,7 +721,7 @@ void MediaNotificationService::SetDialogDelegate(
}
media_message_center::RecordConcurrentNotificationCount(
active_controllable_session_ids_.size());
notification_ids.size());
if (cast_notification_provider_) {
media_message_center::RecordConcurrentCastNotificationCount(
......@@ -726,7 +730,7 @@ void MediaNotificationService::SetDialogDelegate(
}
bool MediaNotificationService::HasActiveNotifications() const {
return !active_controllable_session_ids_.empty();
return !GetActiveControllableNotificationIds().empty();
}
bool MediaNotificationService::HasFrozenNotifications() const {
......@@ -854,22 +858,26 @@ MediaNotificationService::Session* MediaNotificationService::GetSession(
base::WeakPtr<media_message_center::MediaNotificationItem>
MediaNotificationService::GetNonSessionNotificationItem(const std::string& id) {
if (cast_notification_provider_) {
auto item = cast_notification_provider_->GetNotificationItem(id);
if (item)
for (auto* notification_provider : notification_providers_) {
auto item = notification_provider->GetNotificationItem(id);
if (item) {
return item;
}
if (presentation_request_notification_provider_) {
auto item =
presentation_request_notification_provider_->GetNotificationItem(id);
if (item)
return item;
}
return nullptr;
}
std::set<std::string>
MediaNotificationService::GetActiveControllableNotificationIds() const {
std::set<std::string> ids = active_controllable_session_ids_;
for (auto* notification_provider : notification_providers_) {
const std::set<std::string>& provider_ids =
notification_provider->GetActiveControllableNotificationIds();
ids.insert(provider_ids.begin(), provider_ids.end());
}
return ids;
}
void MediaNotificationService::OnNotificationChanged(
const std::string* changed_notification_id) {
for (auto& observer : observers_)
......
......@@ -307,6 +307,8 @@ class MediaNotificationService
base::WeakPtr<media_message_center::MediaNotificationItem>
GetNonSessionNotificationItem(const std::string& id);
std::set<std::string> GetActiveControllableNotificationIds() const;
// Called after changing anything about a notification to notify any observers
// and update the visibility of supplemental notifications. If the change is
// associated with a particular notification ID, that ID should be passed as
......@@ -321,23 +323,23 @@ class MediaNotificationService
// Used to track whether there are any active controllable sessions. If not,
// then there's nothing to show in the dialog and we can hide the toolbar
// icon. Contains sessions from both Media Session API and Cast.
std::unordered_set<std::string> active_controllable_session_ids_;
// icon. Contains sessions from the Media Session API.
std::set<std::string> active_controllable_session_ids_;
// Tracks the sessions that are currently frozen. If there are only frozen
// sessions, we will disable the toolbar icon and wait to hide it.
std::unordered_set<std::string> frozen_session_ids_;
std::set<std::string> frozen_session_ids_;
// Tracks the sessions that are currently dragged out of the dialog. These
// should not be shown in the dialog and will be ignored for showing the
// toolbar icon.
std::unordered_set<std::string> dragged_out_session_ids_;
std::set<std::string> dragged_out_session_ids_;
// Tracks the sessions that are currently inactive. Sessions become inactive
// after a period of time of being paused with no user interaction. Inactive
// sessions are hidden from the dialog until the user interacts with them
// again (e.g. by playing the session).
std::unordered_set<std::string> inactive_session_ids_;
std::set<std::string> inactive_session_ids_;
// A mapping of supplemental notification IDs to their associated web
// contents. See MediaNotificationController::AddSupplementalNotification for
......@@ -366,6 +368,9 @@ class MediaNotificationService
std::unique_ptr<PresentationRequestNotificationProvider>
presentation_request_notification_provider_;
// Pointers to all notification providers owned by |this|.
std::set<MediaNotificationProducer*> notification_providers_;
base::ObserverList<MediaNotificationServiceObserver> observers_;
// Tracks the number of times we have recorded an action for a specific
......
......@@ -59,6 +59,12 @@ PresentationRequestNotificationProvider::GetNotificationItem(
return nullptr;
}
std::set<std::string>
PresentationRequestNotificationProvider::GetActiveControllableNotificationIds()
const {
return item_ ? std::set<std::string>({item_->id()}) : std::set<std::string>();
}
void PresentationRequestNotificationProvider::OnStartPresentationContextCreated(
std::unique_ptr<media_router::StartPresentationContext> context) {
DCHECK(context);
......@@ -69,9 +75,9 @@ void PresentationRequestNotificationProvider::OnStartPresentationContextCreated(
void PresentationRequestNotificationProvider::OnNotificationListChanged() {}
void PresentationRequestNotificationProvider::OnMediaDialogOpened() {
// At the point where this method is called, MediaNotificationService is in
// a state where it can't accept new notifications. As a workaround, we
// simply defer the handling of the event.
// At the point where this method is called, MediaNotificationService is
// in a state where it can't accept new notifications. As a workaround,
// we simply defer the handling of the event.
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(
......@@ -92,17 +98,17 @@ void PresentationRequestNotificationProvider::OnMediaDialogClosed() {
void PresentationRequestNotificationProvider::AfterMediaDialogOpened(
base::WeakPtr<media_router::WebContentsPresentationManager>
presentation_manager) {
// It's possible the presentation manager was deleted since the call to this
// method was scheduled.
// It's possible the presentation manager was deleted since the call to
// this method was scheduled.
if (!presentation_manager)
return;
presentation_manager->AddObserver(this);
// Handle any request that was created while we weren't watching, first making
// sure the dialog hasn't been closed since the we found out it was opening.
// This is the normal way notifications are created for a default presentation
// request.
// Handle any request that was created while we weren't watching, first
// making sure the dialog hasn't been closed since the we found out it was
// opening. This is the normal way notifications are created for a default
// presentation request.
if (presentation_manager->HasDefaultPresentationRequest() &&
notification_service_->HasOpenDialog()) {
OnDefaultPresentationChanged(
......@@ -121,10 +127,11 @@ void PresentationRequestNotificationProvider::AfterMediaDialogClosed(
void PresentationRequestNotificationProvider::OnDefaultPresentationChanged(
const content::PresentationRequest* presentation_request) {
// NOTE: We only observe the presentation manager while the media control
// dialog is open, so this method is only handling the unusual case where the
// default presentation request is changed while the dialog is open. In the
// even more unusual case where the dialog is already open with a notification
// for a non-default request, we ignored changes in the default request.
// dialog is open, so this method is only handling the unusual case where
// the default presentation request is changed while the dialog is open.
// In the even more unusual case where the dialog is already open with a
// notification for a non-default request, we ignored changes in the
// default request.
if (!HasItemForNonDefaultRequest()) {
if (presentation_request) {
CreateItemForPresentationRequest(*presentation_request, nullptr);
......@@ -137,8 +144,8 @@ void PresentationRequestNotificationProvider::OnDefaultPresentationChanged(
void PresentationRequestNotificationProvider::CreateItemForPresentationRequest(
const content::PresentationRequest& request,
std::unique_ptr<media_router::StartPresentationContext> context) {
// This may replace an existing item, which is the right thing to do if we've
// reached this point.
// This may replace an existing item, which is the right thing to do if
// we've reached this point.
item_.emplace(notification_service_, request, std::move(context));
auto* rfh = content::RenderFrameHost::FromID(request.render_frame_host_id);
......
......@@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "chrome/browser/ui/global_media_controls/media_notification_producer.h"
#include "chrome/browser/ui/global_media_controls/media_notification_service_observer.h"
#include "chrome/browser/ui/global_media_controls/presentation_request_notification_item.h"
#include "components/media_router/browser/presentation/web_contents_presentation_manager.h"
......@@ -39,7 +40,8 @@
// involved; at that point CastMediaNotificationProvider become responsible for
// managing the notification for an active session.
class PresentationRequestNotificationProvider final
: public media_router::WebContentsPresentationManager::Observer,
: public MediaNotificationProducer,
public media_router::WebContentsPresentationManager::Observer,
public MediaNotificationServiceObserver {
public:
explicit PresentationRequestNotificationProvider(
......@@ -50,14 +52,16 @@ class PresentationRequestNotificationProvider final
const PresentationRequestNotificationProvider&) = delete;
~PresentationRequestNotificationProvider() final;
// MediaNotificationProducer:
base::WeakPtr<media_message_center::MediaNotificationItem>
GetNotificationItem(const std::string& id);
GetNotificationItem(const std::string& id) override;
std::set<std::string> GetActiveControllableNotificationIds() const override;
void OnStartPresentationContextCreated(
std::unique_ptr<media_router::StartPresentationContext> context);
private:
// MediaNotificationServiceObserver
// MediaNotificationServiceObserver:
void OnNotificationListChanged() final;
void OnMediaDialogOpened() final;
void OnMediaDialogClosed() final;
......@@ -69,7 +73,7 @@ class PresentationRequestNotificationProvider final
base::WeakPtr<media_router::WebContentsPresentationManager>
presentation_manager);
// WebContentsPresentationManager::Observer
// WebContentsPresentationManager::Observer:
void OnDefaultPresentationChanged(
const content::PresentationRequest* presentation_request) final;
......
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