Commit d8325b8e authored by Tommy Steimel's avatar Tommy Steimel Committed by Commit Bot

GMC: Show a list of all media sessions instead of just the active one

This CL updates the global media controls UI to show all media sessions
instead of just the most recently active media session.

Bug: 973492
Change-Id: Ib0943d4044ee3c036a1b783785695ebba09eb0f4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1695989Reviewed-by: default avatarBecca Hughes <beccahughes@chromium.org>
Commit-Queue: Tommy Steimel <steimel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#676119}
parent 07a7b98b
...@@ -2738,6 +2738,8 @@ jumbo_split_static_library("ui") { ...@@ -2738,6 +2738,8 @@ jumbo_split_static_library("ui") {
"views/global_media_controls/media_dialog_view.h", "views/global_media_controls/media_dialog_view.h",
"views/global_media_controls/media_notification_container_impl.cc", "views/global_media_controls/media_notification_container_impl.cc",
"views/global_media_controls/media_notification_container_impl.h", "views/global_media_controls/media_notification_container_impl.h",
"views/global_media_controls/media_notification_list_view.cc",
"views/global_media_controls/media_notification_list_view.h",
"views/global_media_controls/media_toolbar_button_view.cc", "views/global_media_controls/media_toolbar_button_view.cc",
"views/global_media_controls/media_toolbar_button_view.h", "views/global_media_controls/media_toolbar_button_view.h",
"views/hover_button.cc", "views/hover_button.cc",
......
...@@ -88,16 +88,6 @@ void MediaDialogController::HideNotification(const std::string& id) { ...@@ -88,16 +88,6 @@ void MediaDialogController::HideNotification(const std::string& id) {
void MediaDialogController::OnReceivedAudioFocusRequests( void MediaDialogController::OnReceivedAudioFocusRequests(
std::vector<media_session::mojom::AudioFocusRequestStatePtr> sessions) { std::vector<media_session::mojom::AudioFocusRequestStatePtr> sessions) {
// TODO(steimel): Show all controllable sessions. for (auto& session : sessions)
media_session::mojom::AudioFocusRequestStatePtr active_session; OnFocusGained(std::move(session));
for (auto& session : base::Reversed(sessions)) {
if (!session->session_info->is_controllable)
continue;
active_session = session.Clone();
break;
}
if (active_session)
OnFocusGained(std::move(active_session));
} }
...@@ -48,7 +48,7 @@ class MediaDialogControllerTest : public testing::Test { ...@@ -48,7 +48,7 @@ class MediaDialogControllerTest : public testing::Test {
} }
protected: protected:
void SimulateFocusGained(const base::UnguessableToken& id, AudioFocusRequestStatePtr CreateFocusRequest(const base::UnguessableToken& id,
bool controllable) { bool controllable) {
MediaSessionInfoPtr session_info(MediaSessionInfo::New()); MediaSessionInfoPtr session_info(MediaSessionInfo::New());
session_info->is_controllable = controllable; session_info->is_controllable = controllable;
...@@ -56,7 +56,12 @@ class MediaDialogControllerTest : public testing::Test { ...@@ -56,7 +56,12 @@ class MediaDialogControllerTest : public testing::Test {
AudioFocusRequestStatePtr focus(AudioFocusRequestState::New()); AudioFocusRequestStatePtr focus(AudioFocusRequestState::New());
focus->request_id = id; focus->request_id = id;
focus->session_info = std::move(session_info); focus->session_info = std::move(session_info);
controller_->OnFocusGained(std::move(focus)); return focus;
}
void SimulateFocusGained(const base::UnguessableToken& id,
bool controllable) {
controller_->OnFocusGained(CreateFocusRequest(id, controllable));
} }
void SimulateFocusLost(const base::UnguessableToken& id) { void SimulateFocusLost(const base::UnguessableToken& id) {
...@@ -81,6 +86,11 @@ class MediaDialogControllerTest : public testing::Test { ...@@ -81,6 +86,11 @@ class MediaDialogControllerTest : public testing::Test {
item_itr->second.MediaSessionMetadataChanged(std::move(metadata)); item_itr->second.MediaSessionMetadataChanged(std::move(metadata));
} }
void SimulateReceivedAudioFocusRequests(
std::vector<AudioFocusRequestStatePtr> requests) {
controller_->OnReceivedAudioFocusRequests(std::move(requests));
}
MockMediaDialogControllerDelegate& delegate() { return delegate_; } MockMediaDialogControllerDelegate& delegate() { return delegate_; }
private: private:
...@@ -113,3 +123,25 @@ TEST_F(MediaDialogControllerTest, DoesNotShowUncontrollableSession) { ...@@ -113,3 +123,25 @@ TEST_F(MediaDialogControllerTest, DoesNotShowUncontrollableSession) {
SimulateFocusGained(id, false); SimulateFocusGained(id, false);
SimulateNecessaryMetadata(id); SimulateNecessaryMetadata(id);
} }
TEST_F(MediaDialogControllerTest, ShowsAllInitialControllableSessions) {
base::UnguessableToken controllable1_id = base::UnguessableToken::Create();
base::UnguessableToken uncontrollable_id = base::UnguessableToken::Create();
base::UnguessableToken controllable2_id = base::UnguessableToken::Create();
EXPECT_CALL(delegate(), ShowMediaSession(controllable1_id.ToString(), _));
EXPECT_CALL(delegate(), ShowMediaSession(uncontrollable_id.ToString(), _))
.Times(0);
EXPECT_CALL(delegate(), ShowMediaSession(controllable2_id.ToString(), _));
std::vector<AudioFocusRequestStatePtr> requests;
requests.push_back(CreateFocusRequest(controllable1_id, true));
requests.push_back(CreateFocusRequest(uncontrollable_id, false));
requests.push_back(CreateFocusRequest(controllable2_id, true));
SimulateReceivedAudioFocusRequests(std::move(requests));
SimulateNecessaryMetadata(controllable1_id);
SimulateNecessaryMetadata(uncontrollable_id);
SimulateNecessaryMetadata(controllable2_id);
}
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h" #include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h"
#include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h"
#include "services/media_session/public/mojom/media_session.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h"
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
...@@ -48,27 +49,13 @@ bool MediaDialogView::IsShowing() { ...@@ -48,27 +49,13 @@ bool MediaDialogView::IsShowing() {
void MediaDialogView::ShowMediaSession( void MediaDialogView::ShowMediaSession(
const std::string& id, const std::string& id,
base::WeakPtr<media_message_center::MediaNotificationItem> item) { base::WeakPtr<media_message_center::MediaNotificationItem> item) {
// Do nothing if we're already showing this media session. active_sessions_view_->ShowNotification(
if (active_session_id_.has_value() && *active_session_id_ == id) id, std::make_unique<MediaNotificationContainerImpl>(this, item));
return;
active_session_id_ = id;
auto active_session_container =
std::make_unique<MediaNotificationContainerImpl>(this, item);
active_session_container_ = AddChildView(std::move(active_session_container));
OnAnchorBoundsChanged(); OnAnchorBoundsChanged();
} }
void MediaDialogView::HideMediaSession(const std::string& id) { void MediaDialogView::HideMediaSession(const std::string& id) {
// Do nothing if we're not showing this media session. active_sessions_view_->HideNotification(id);
if (!active_session_id_.has_value() || active_session_id_ != id)
return;
active_session_id_ = base::nullopt;
RemoveChildView(active_session_container_);
active_session_container_ = nullptr;
OnAnchorBoundsChanged(); OnAnchorBoundsChanged();
} }
...@@ -86,7 +73,7 @@ bool MediaDialogView::Close() { ...@@ -86,7 +73,7 @@ bool MediaDialogView::Close() {
gfx::Size MediaDialogView::CalculatePreferredSize() const { gfx::Size MediaDialogView::CalculatePreferredSize() const {
// If we have an active session, then fit to it. // If we have an active session, then fit to it.
if (active_session_container_) if (!active_sessions_view_->empty())
return views::BubbleDialogDelegateView::CalculatePreferredSize(); return views::BubbleDialogDelegateView::CalculatePreferredSize();
// Otherwise, use a standard size for bubble dialogs. // Otherwise, use a standard size for bubble dialogs.
...@@ -98,7 +85,9 @@ gfx::Size MediaDialogView::CalculatePreferredSize() const { ...@@ -98,7 +85,9 @@ gfx::Size MediaDialogView::CalculatePreferredSize() const {
MediaDialogView::MediaDialogView(views::View* anchor_view, MediaDialogView::MediaDialogView(views::View* anchor_view,
service_manager::Connector* connector) service_manager::Connector* connector)
: BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT),
controller_(connector, this) {} controller_(connector, this),
active_sessions_view_(
AddChildView(std::make_unique<MediaNotificationListView>())) {}
MediaDialogView::~MediaDialogView() = default; MediaDialogView::~MediaDialogView() = default;
......
...@@ -14,7 +14,7 @@ namespace service_manager { ...@@ -14,7 +14,7 @@ namespace service_manager {
class Connector; class Connector;
} // namespace service_manager } // namespace service_manager
class MediaNotificationContainerImpl; class MediaNotificationListView;
// Dialog that shows media controls that control the active media session. // Dialog that shows media controls that control the active media session.
class MediaDialogView : public views::BubbleDialogDelegateView, class MediaDialogView : public views::BubbleDialogDelegateView,
...@@ -54,11 +54,7 @@ class MediaDialogView : public views::BubbleDialogDelegateView, ...@@ -54,11 +54,7 @@ class MediaDialogView : public views::BubbleDialogDelegateView,
MediaDialogController controller_; MediaDialogController controller_;
// TODO(steimel): We should support showing multiple sessions instead of just MediaNotificationListView* const active_sessions_view_;
// the active one.
MediaNotificationContainerImpl* active_session_container_ = nullptr;
base::Optional<std::string> active_session_id_;
DISALLOW_COPY_AND_ASSIGN(MediaDialogView); DISALLOW_COPY_AND_ASSIGN(MediaDialogView);
}; };
......
// 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.
#include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h"
#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl.h"
#include "ui/views/layout/box_layout.h"
MediaNotificationListView::MediaNotificationListView() {
SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kVertical));
}
MediaNotificationListView::~MediaNotificationListView() = default;
void MediaNotificationListView::ShowNotification(
const std::string& id,
std::unique_ptr<MediaNotificationContainerImpl> notification) {
DCHECK(!base::Contains(notifications_, id));
DCHECK_NE(nullptr, notification.get());
notifications_[id] = AddChildView(std::move(notification));
PreferredSizeChanged();
}
void MediaNotificationListView::HideNotification(const std::string& id) {
if (!base::Contains(notifications_, id))
return;
RemoveChildView(notifications_[id]);
notifications_.erase(id);
PreferredSizeChanged();
}
// 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_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_LIST_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_LIST_VIEW_H_
#include <map>
#include <memory>
#include "ui/views/view.h"
class MediaNotificationContainerImpl;
// MediaNotificationListView is a container that holds a list of active media
// sessions.
class MediaNotificationListView : public views::View {
public:
MediaNotificationListView();
~MediaNotificationListView() override;
void ShowNotification(
const std::string& id,
std::unique_ptr<MediaNotificationContainerImpl> notification);
void HideNotification(const std::string& id);
bool empty() { return notifications_.empty(); }
private:
std::map<const std::string, MediaNotificationContainerImpl*> notifications_;
DISALLOW_COPY_AND_ASSIGN(MediaNotificationListView);
};
#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_LIST_VIEW_H_
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