Commit db6c36a3 authored by Jazz Xu's avatar Jazz Xu Committed by Commit Bot

CrOS GMC: Navigate to detailed view when media controls is clicked.

This CL adds media controls detailed view. When media controls is
clicked outside of action buttons, we will navigate user to a
detailed view showing all playing media.

Bug: 1129784
Change-Id: I9b84089caacc36229664096af0fbf4f8a31b3f74
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2416682
Commit-Queue: Jazz Xu <jazzhsu@chromium.org>
Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Reviewed-by: default avatarJenny Zhang <jennyz@chromium.org>
Reviewed-by: default avatarTim Song <tengs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809528}
parent 79f614a3
...@@ -972,6 +972,10 @@ component("ash") { ...@@ -972,6 +972,10 @@ component("ash") {
"system/media/unified_media_controls_container.h", "system/media/unified_media_controls_container.h",
"system/media/unified_media_controls_controller.cc", "system/media/unified_media_controls_controller.cc",
"system/media/unified_media_controls_controller.h", "system/media/unified_media_controls_controller.h",
"system/media/unified_media_controls_detailed_view.cc",
"system/media/unified_media_controls_detailed_view.h",
"system/media/unified_media_controls_detailed_view_controller.cc",
"system/media/unified_media_controls_detailed_view_controller.h",
"system/media/unified_media_controls_view.cc", "system/media/unified_media_controls_view.cc",
"system/media/unified_media_controls_view.h", "system/media/unified_media_controls_view.h",
"system/message_center/arc_notification_manager_delegate_impl.cc", "system/message_center/arc_notification_manager_delegate_impl.cc",
...@@ -2077,6 +2081,7 @@ test("ash_unittests") { ...@@ -2077,6 +2081,7 @@ test("ash_unittests") {
"system/machine_learning/user_settings_event_logger_unittest.cc", "system/machine_learning/user_settings_event_logger_unittest.cc",
"system/media/media_tray_unittest.cc", "system/media/media_tray_unittest.cc",
"system/media/unified_media_controls_controller_unittest.cc", "system/media/unified_media_controls_controller_unittest.cc",
"system/media/unified_media_controls_detailed_view_controller_unittest.cc",
"system/message_center/ash_message_popup_collection_unittest.cc", "system/message_center/ash_message_popup_collection_unittest.cc",
"system/message_center/inactive_user_notification_blocker_unittest.cc", "system/message_center/inactive_user_notification_blocker_unittest.cc",
"system/message_center/message_center_ui_controller_unittest.cc", "system/message_center/message_center_ui_controller_unittest.cc",
......
...@@ -234,6 +234,9 @@ This file contains the strings for ash. ...@@ -234,6 +234,9 @@ This file contains the strings for ash.
<message name="IDS_ASH_QUICK_SETTINGS_BUBBLE_VPN_SETTINGS_ACCESSIBLE_DESCRIPTION" desc="The accessible description for VPN settings accessed through the VPN feature pod."> <message name="IDS_ASH_QUICK_SETTINGS_BUBBLE_VPN_SETTINGS_ACCESSIBLE_DESCRIPTION" desc="The accessible description for VPN settings accessed through the VPN feature pod.">
VPN Settings VPN Settings
</message> </message>
<message name="IDS_ASH_QUICK_SETTINGS_BUBBLE_MEDIA_CONTROLS_ACCESSIBLE_DESCRIPTION" is_accessibility_with_no_ui="true" desc="The accessible description for global media controls accessed through the media controls pod.">
Media Controls
</message>
<message name="IDS_ASH_STATUS_TRAY_BRAILLE_DISPLAY_CONNECTED" desc="The message shown on a notification when a braille display is connected"> <message name="IDS_ASH_STATUS_TRAY_BRAILLE_DISPLAY_CONNECTED" desc="The message shown on a notification when a braille display is connected">
Braille display connected. Braille display connected.
</message> </message>
......
...@@ -143,6 +143,10 @@ void UnifiedMediaControlsController::MediaControllerImageChanged( ...@@ -143,6 +143,10 @@ void UnifiedMediaControlsController::MediaControllerImageChanged(
media_controls_->SetArtwork(session_artwork); media_controls_->SetArtwork(session_artwork);
} }
void UnifiedMediaControlsController::OnMediaControlsViewClicked() {
delegate_->OnMediaControlsViewClicked();
}
void UnifiedMediaControlsController::PerformAction( void UnifiedMediaControlsController::PerformAction(
media_session::mojom::MediaSessionAction action) { media_session::mojom::MediaSessionAction action) {
media_session::PerformMediaSessionAction(action, media_controller_remote_); media_session::PerformMediaSessionAction(action, media_controller_remote_);
......
...@@ -31,6 +31,7 @@ class ASH_EXPORT UnifiedMediaControlsController ...@@ -31,6 +31,7 @@ class ASH_EXPORT UnifiedMediaControlsController
virtual ~Delegate() = default; virtual ~Delegate() = default;
virtual void ShowMediaControls() = 0; virtual void ShowMediaControls() = 0;
virtual void HideMediaControls() = 0; virtual void HideMediaControls() = 0;
virtual void OnMediaControlsViewClicked() = 0;
}; };
explicit UnifiedMediaControlsController(Delegate* deleate); explicit UnifiedMediaControlsController(Delegate* deleate);
...@@ -56,6 +57,8 @@ class ASH_EXPORT UnifiedMediaControlsController ...@@ -56,6 +57,8 @@ class ASH_EXPORT UnifiedMediaControlsController
views::View* CreateView(); views::View* CreateView();
void OnMediaControlsViewClicked();
// Called from view when media buttons are pressed. // Called from view when media buttons are pressed.
void PerformAction(media_session::mojom::MediaSessionAction action); void PerformAction(media_session::mojom::MediaSessionAction action);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "media/base/media_switches.h" #include "media/base/media_switches.h"
#include "services/media_session/public/cpp/test/test_media_controller.h" #include "services/media_session/public/cpp/test/test_media_controller.h"
#include "services/media_session/public/mojom/media_session.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "ui/events/test/event_generator.h" #include "ui/events/test/event_generator.h"
#include "ui/views/controls/image_view.h" #include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h" #include "ui/views/controls/label.h"
...@@ -35,6 +36,7 @@ class MockMediaControlsDelegate ...@@ -35,6 +36,7 @@ class MockMediaControlsDelegate
void ShowMediaControls() override { visible_ = true; } void ShowMediaControls() override { visible_ = true; }
void HideMediaControls() override { visible_ = false; } void HideMediaControls() override { visible_ = false; }
MOCK_METHOD0(OnMediaControlsViewClicked, void());
bool IsControlsVisible() { return visible_; } bool IsControlsVisible() { return visible_; }
...@@ -143,6 +145,10 @@ class UnifiedMediaControlsControllerTest : public AshTestBase { ...@@ -143,6 +145,10 @@ class UnifiedMediaControlsControllerTest : public AshTestBase {
TestMediaController* media_controller() { return media_controller_.get(); } TestMediaController* media_controller() { return media_controller_.get(); }
UnifiedMediaControlsView* media_controls_view() {
return media_controls_.get();
}
private: private:
void NotifyActionsChanged() { void NotifyActionsChanged() {
controller_->MediaSessionActionsChanged( controller_->MediaSessionActionsChanged(
...@@ -304,4 +310,15 @@ TEST_F(UnifiedMediaControlsControllerTest, ...@@ -304,4 +310,15 @@ TEST_F(UnifiedMediaControlsControllerTest,
EXPECT_FALSE(delegate()->IsControlsVisible()); EXPECT_FALSE(delegate()->IsControlsVisible());
} }
TEST_F(UnifiedMediaControlsControllerTest,
NotifyDelegateWhenMediaControlsViewClicked) {
CreateWidget();
EXPECT_CALL(*delegate(), OnMediaControlsViewClicked);
ui::test::EventGenerator* generator = GetEventGenerator();
generator->MoveMouseTo(
media_controls_view()->GetBoundsInScreen().CenterPoint());
generator->ClickLeftButton();
}
} // namespace ash } // namespace ash
// 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 "ash/system/media/unified_media_controls_detailed_view.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
namespace ash {
UnifiedMediaControlsDetailedView::UnifiedMediaControlsDetailedView(
DetailedViewDelegate* delegate,
std::unique_ptr<views::View> notification_list_view)
: TrayDetailedView(delegate) {
CreateTitleRow(IDS_ASH_GLOBAL_MEDIA_CONTROLS_TITLE);
notification_list_view->SetBorder(views::CreateSolidSidedBorder(
0 /* top */, 0 /* left */, kMenuSeparatorWidth /* bottom */,
0 /* right */,
AshColorProvider::Get()->GetContentLayerColor(
AshColorProvider::ContentLayerType::kSeparatorColor)));
AddChildView(std::move(notification_list_view));
}
} // namespace ash
// 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.
#ifndef ASH_SYSTEM_MEDIA_UNIFIED_MEDIA_CONTROLS_DETAILED_VIEW_H_
#define ASH_SYSTEM_MEDIA_UNIFIED_MEDIA_CONTROLS_DETAILED_VIEW_H_
#include "ash/system/tray/tray_detailed_view.h"
namespace ash {
// Detailed view displaying all active media sessions
class UnifiedMediaControlsDetailedView : public TrayDetailedView {
public:
UnifiedMediaControlsDetailedView(
DetailedViewDelegate* delegate,
std::unique_ptr<views::View> notification_list_view);
~UnifiedMediaControlsDetailedView() override = default;
};
} // namespace ash
#endif // ASH_SYSTEM_MEDIA_UNIFIED_MEDIA_CONTROLS_DETAILED_VIEW_H_
// 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 "ash/system/media/unified_media_controls_detailed_view_controller.h"
#include "ash/public/cpp/media_notification_provider.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h"
#include "ash/system/media/unified_media_controls_detailed_view.h"
#include "ash/system/tray/detailed_view_delegate.h"
#include "ash/system/tray/tray_constants.h"
#include "ui/base/l10n/l10n_util.h"
namespace ash {
UnifiedMediaControlsDetailedViewController::
UnifiedMediaControlsDetailedViewController(
UnifiedSystemTrayController* tray_controller)
: detailed_view_delegate_(
std::make_unique<DetailedViewDelegate>(tray_controller)) {
DCHECK(MediaNotificationProvider::Get());
MediaNotificationProvider::Get()->AddObserver(this);
}
UnifiedMediaControlsDetailedViewController::
~UnifiedMediaControlsDetailedViewController() {
if (!MediaNotificationProvider::Get())
return;
MediaNotificationProvider::Get()->RemoveObserver(this);
MediaNotificationProvider::Get()->OnBubbleClosing();
}
views::View* UnifiedMediaControlsDetailedViewController::CreateView() {
DCHECK(MediaNotificationProvider::Get());
return new UnifiedMediaControlsDetailedView(
detailed_view_delegate_.get(),
MediaNotificationProvider::Get()->GetMediaNotificationListView(
AshColorProvider::Get()->GetContentLayerColor(
AshColorProvider::ContentLayerType::kSeparatorColor),
kMenuSeparatorWidth));
}
base::string16 UnifiedMediaControlsDetailedViewController::GetAccessibleName()
const {
return l10n_util::GetStringUTF16(
IDS_ASH_QUICK_SETTINGS_BUBBLE_MEDIA_CONTROLS_ACCESSIBLE_DESCRIPTION);
}
void UnifiedMediaControlsDetailedViewController::OnNotificationListChanged() {
DCHECK(MediaNotificationProvider::Get());
if (MediaNotificationProvider::Get()->HasActiveNotifications() ||
MediaNotificationProvider::Get()->HasFrozenNotifications())
return;
detailed_view_delegate_->TransitionToMainView(false /* restore_focus */);
}
} // namespace ash
// 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.
#ifndef ASH_SYSTEM_MEDIA_UNIFIED_MEDIA_CONTROLS_DETAILED_VIEW_CONTROLLER_H_
#define ASH_SYSTEM_MEDIA_UNIFIED_MEDIA_CONTROLS_DETAILED_VIEW_CONTROLLER_H_
#include "ash/ash_export.h"
#include "ash/public/cpp/media_notification_provider_observer.h"
#include "ash/system/unified/detailed_view_controller.h"
namespace ash {
class DetailedViewDelegate;
class UnifiedSystemTrayController;
// Controller of UnifiedMediaControlsDetailedView in UnifiedSystemTray.
class ASH_EXPORT UnifiedMediaControlsDetailedViewController
: public DetailedViewController,
public MediaNotificationProviderObserver {
public:
explicit UnifiedMediaControlsDetailedViewController(
UnifiedSystemTrayController* tray_controller);
~UnifiedMediaControlsDetailedViewController() override;
// DetailedViewController implementations.
views::View* CreateView() override;
base::string16 GetAccessibleName() const override;
// MediaNotificationProviderObserver implementations.
void OnNotificationListChanged() override;
void OnNotificationListViewSizeChanged() override {}
private:
const std::unique_ptr<DetailedViewDelegate> detailed_view_delegate_;
};
} // namespace ash
#endif // ASH_SYSTEM_MEDIA_UNIFIED_MEDIA_CONTROLS_DETAILED_VIEW_CONTROLLER_H_
// 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 "ash/system/media/unified_media_controls_detailed_view_controller.h"
#include "ash/public/cpp/media_notification_provider.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/status_area_widget_test_helper.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/system/unified/unified_system_tray_bubble.h"
#include "ash/system/unified/unified_system_tray_controller.h"
#include "ash/test/ash_test_base.h"
#include "testing/gmock/include/gmock/gmock.h"
using ::testing::_;
namespace ash {
namespace {
class MockMediaNotificationProvider : MediaNotificationProvider {
public:
MockMediaNotificationProvider() {
MediaNotificationProvider::Set(this);
ON_CALL(*this, GetMediaNotificationListView(_, _))
.WillByDefault(
[](auto, auto) { return std::make_unique<views::View>(); });
}
~MockMediaNotificationProvider() override {
MediaNotificationProvider::Set(nullptr);
}
// MediaNotificationProvider implementations.
MOCK_METHOD2(GetMediaNotificationListView,
std::unique_ptr<views::View>(SkColor, int));
MOCK_METHOD0(OnBubbleClosing, void());
std::unique_ptr<views::View> GetActiveMediaNotificationView() override {
return std::make_unique<views::View>();
}
void AddObserver(MediaNotificationProviderObserver* observer) override {}
void RemoveObserver(MediaNotificationProviderObserver* observer) override {}
bool HasActiveNotifications() override { return has_active_notifications_; }
bool HasFrozenNotifications() override { return has_frozen_notifications_; }
void SetHasActiveNotifications(bool has_active_notifications) {
has_active_notifications_ = has_active_notifications;
}
void SetHasFrozenNotifications(bool has_frozen_notifications) {
has_frozen_notifications_ = has_frozen_notifications;
}
private:
bool has_active_notifications_ = false;
bool has_frozen_notifications_ = false;
};
} // namespace
class UnifiedMediaControlsDetailedViewControllerTest : public AshTestBase {
public:
UnifiedMediaControlsDetailedViewControllerTest() = default;
~UnifiedMediaControlsDetailedViewControllerTest() override = default;
void SetUp() override {
provider_ = std::make_unique<MockMediaNotificationProvider>();
AshTestBase::SetUp();
StatusAreaWidgetTestHelper::GetStatusAreaWidget()
->unified_system_tray()
->ShowBubble(false /* show_by_click */);
}
void TearDown() override {
AshTestBase::TearDown();
provider_.reset();
}
UnifiedSystemTrayController* system_tray_controller() {
return StatusAreaWidgetTestHelper::GetStatusAreaWidget()
->unified_system_tray()
->bubble()
->controller_for_test();
}
MockMediaNotificationProvider* provider() { return provider_.get(); }
private:
std::unique_ptr<MockMediaNotificationProvider> provider_;
};
TEST_F(UnifiedMediaControlsDetailedViewControllerTest,
ExitDetailedViewWhenNoMediaIsPlaying) {
// UnifiedSystemTrayController should have no DetailedViewController
// initially.
EXPECT_EQ(system_tray_controller()->detailed_view_controller(), nullptr);
// We should get a MediaNotificationProvider::GetMediaNotificationListView
// call when creating the detailed view.
EXPECT_CALL(*provider(), GetMediaNotificationListView);
system_tray_controller()->OnMediaControlsViewClicked();
EXPECT_NE(system_tray_controller()->detailed_view_controller(), nullptr);
// Notification list update with neither active nor frozen session should
// close the detailed view and get back to main view.
EXPECT_CALL(*provider(), OnBubbleClosing);
static_cast<UnifiedMediaControlsDetailedViewController*>(
system_tray_controller()->detailed_view_controller())
->OnNotificationListChanged();
EXPECT_EQ(system_tray_controller()->detailed_view_controller(), nullptr);
}
} // namespace ash
...@@ -115,7 +115,7 @@ void UnifiedMediaControlsView::MediaActionButton::SetAction( ...@@ -115,7 +115,7 @@ void UnifiedMediaControlsView::MediaActionButton::SetAction(
UnifiedMediaControlsView::UnifiedMediaControlsView( UnifiedMediaControlsView::UnifiedMediaControlsView(
UnifiedMediaControlsController* controller) UnifiedMediaControlsController* controller)
: controller_(controller) { : views::Button(this), controller_(controller) {
SetBackground(views::CreateRoundedRectBackground( SetBackground(views::CreateRoundedRectBackground(
AshColorProvider::Get()->GetControlsLayerColor( AshColorProvider::Get()->GetControlsLayerColor(
AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive), AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive),
...@@ -179,6 +179,11 @@ UnifiedMediaControlsView::UnifiedMediaControlsView( ...@@ -179,6 +179,11 @@ UnifiedMediaControlsView::UnifiedMediaControlsView(
void UnifiedMediaControlsView::ButtonPressed(views::Button* sender, void UnifiedMediaControlsView::ButtonPressed(views::Button* sender,
const ui::Event& event) { const ui::Event& event) {
if (sender == this) {
controller_->OnMediaControlsViewClicked();
return;
}
controller_->PerformAction( controller_->PerformAction(
media_message_center::GetActionFromButtonTag(*sender)); media_message_center::GetActionFromButtonTag(*sender));
} }
......
...@@ -11,7 +11,6 @@ ...@@ -11,7 +11,6 @@
#include "services/media_session/public/mojom/media_session.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h"
#include "ui/views/controls/button/button.h" #include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/image_button.h"
#include "ui/views/view.h"
namespace gfx { namespace gfx {
class ImageSkia; class ImageSkia;
...@@ -27,7 +26,7 @@ namespace ash { ...@@ -27,7 +26,7 @@ namespace ash {
class UnifiedMediaControlsController; class UnifiedMediaControlsController;
// Media controls view displayed in quick settings. // Media controls view displayed in quick settings.
class ASH_EXPORT UnifiedMediaControlsView : public views::View, class ASH_EXPORT UnifiedMediaControlsView : public views::Button,
public views::ButtonListener { public views::ButtonListener {
public: public:
explicit UnifiedMediaControlsView(UnifiedMediaControlsController* controller); explicit UnifiedMediaControlsView(UnifiedMediaControlsController* controller);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "ash/system/locale/locale_feature_pod_controller.h" #include "ash/system/locale/locale_feature_pod_controller.h"
#include "ash/system/locale/unified_locale_detailed_view_controller.h" #include "ash/system/locale/unified_locale_detailed_view_controller.h"
#include "ash/system/media/unified_media_controls_controller.h" #include "ash/system/media/unified_media_controls_controller.h"
#include "ash/system/media/unified_media_controls_detailed_view_controller.h"
#include "ash/system/model/clock_model.h" #include "ash/system/model/clock_model.h"
#include "ash/system/model/system_tray_model.h" #include "ash/system/model/system_tray_model.h"
#include "ash/system/network/network_feature_pod_controller.h" #include "ash/system/network/network_feature_pod_controller.h"
...@@ -363,6 +364,11 @@ void UnifiedSystemTrayController::ShowNotifierSettingsView() { ...@@ -363,6 +364,11 @@ void UnifiedSystemTrayController::ShowNotifierSettingsView() {
ShowDetailedView(std::make_unique<UnifiedNotifierSettingsController>(this)); ShowDetailedView(std::make_unique<UnifiedNotifierSettingsController>(this));
} }
void UnifiedSystemTrayController::ShowMediaControlsDetailedView() {
ShowDetailedView(
std::make_unique<UnifiedMediaControlsDetailedViewController>(this));
}
void UnifiedSystemTrayController::TransitionToMainView(bool restore_focus) { void UnifiedSystemTrayController::TransitionToMainView(bool restore_focus) {
detailed_view_controller_.reset(); detailed_view_controller_.reset();
unified_view_->ResetDetailedView(); unified_view_->ResetDetailedView();
...@@ -424,6 +430,10 @@ void UnifiedSystemTrayController::HideMediaControls() { ...@@ -424,6 +430,10 @@ void UnifiedSystemTrayController::HideMediaControls() {
unified_view_->HideMediaControls(); unified_view_->HideMediaControls();
} }
void UnifiedSystemTrayController::OnMediaControlsViewClicked() {
ShowMediaControlsDetailedView();
}
void UnifiedSystemTrayController::InitFeaturePods() { void UnifiedSystemTrayController::InitFeaturePods() {
AddFeaturePodItem(std::make_unique<NetworkFeaturePodController>(this)); AddFeaturePodItem(std::make_unique<NetworkFeaturePodController>(this));
AddFeaturePodItem(std::make_unique<BluetoothFeaturePodController>(this)); AddFeaturePodItem(std::make_unique<BluetoothFeaturePodController>(this));
......
...@@ -93,6 +93,8 @@ class ASH_EXPORT UnifiedSystemTrayController ...@@ -93,6 +93,8 @@ class ASH_EXPORT UnifiedSystemTrayController
void ShowDarkModeDetailedView(); void ShowDarkModeDetailedView();
// Show the detailed view of notifier settings. Called from the view. // Show the detailed view of notifier settings. Called from the view.
void ShowNotifierSettingsView(); void ShowNotifierSettingsView();
// Show the detailed view of media controls. Called from the view.
void ShowMediaControlsDetailedView();
// If you want to add a new detailed view, add here. // If you want to add a new detailed view, add here.
...@@ -133,6 +135,7 @@ class ASH_EXPORT UnifiedSystemTrayController ...@@ -133,6 +135,7 @@ class ASH_EXPORT UnifiedSystemTrayController
// UnifedMediaControlsController::Delegate; // UnifedMediaControlsController::Delegate;
void ShowMediaControls() override; void ShowMediaControls() override;
void HideMediaControls() override; void HideMediaControls() override;
void OnMediaControlsViewClicked() override;
UnifiedSystemTrayModel* model() { return model_; } UnifiedSystemTrayModel* model() { return model_; }
......
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