Commit 3493d21e authored by Jazz Xu's avatar Jazz Xu Committed by Commit Bot

GMC: Add picture-in-picture button to zenith dialog.

This CL adds picture-in-picture button to zenith dialog.
Will follow up with integration tests and unit tests.

Bug: 1047314
Change-Id: Id435d557b2eb80ac8d262da7f137a72b1cc1908c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2030353Reviewed-by: default avatarTommy Steimel <steimel@chromium.org>
Reviewed-by: default avatarEvan Stade <estade@chromium.org>
Reviewed-by: default avatarBecca Hughes <beccahughes@chromium.org>
Commit-Queue: Jazz Xu <jazzhsu@chromium.org>
Commit-Queue: Becca Hughes <beccahughes@chromium.org>
Cr-Commit-Position: refs/heads/master@{#737098}
parent 2860177b
...@@ -217,7 +217,14 @@ void MediaNotificationContainerImplView::OnMediaSessionMetadataChanged() { ...@@ -217,7 +217,14 @@ void MediaNotificationContainerImplView::OnMediaSessionMetadataChanged() {
void MediaNotificationContainerImplView::OnVisibleActionsChanged( void MediaNotificationContainerImplView::OnVisibleActionsChanged(
const base::flat_set<media_session::mojom::MediaSessionAction>& actions) { const base::flat_set<media_session::mojom::MediaSessionAction>& actions) {
has_many_actions_ = actions.size() >= kMinVisibleActionsForExpanding; has_many_actions_ =
(actions.size() >= kMinVisibleActionsForExpanding ||
base::Contains(
actions,
media_session::mojom::MediaSessionAction::kEnterPictureInPicture) ||
base::Contains(
actions,
media_session::mojom::MediaSessionAction::kExitPictureInPicture));
ForceExpandedState(); ForceExpandedState();
} }
......
...@@ -18,9 +18,14 @@ namespace { ...@@ -18,9 +18,14 @@ namespace {
// show all the action buttons then this is used to determine which will be // show all the action buttons then this is used to determine which will be
// shown. // shown.
constexpr MediaSessionAction kPreferredActions[] = { constexpr MediaSessionAction kPreferredActions[] = {
MediaSessionAction::kPlay, MediaSessionAction::kPause, MediaSessionAction::kPlay,
MediaSessionAction::kPreviousTrack, MediaSessionAction::kNextTrack, MediaSessionAction::kPause,
MediaSessionAction::kSeekBackward, MediaSessionAction::kSeekForward, MediaSessionAction::kPreviousTrack,
MediaSessionAction::kNextTrack,
MediaSessionAction::kSeekBackward,
MediaSessionAction::kSeekForward,
MediaSessionAction::kEnterPictureInPicture,
MediaSessionAction::kExitPictureInPicture,
}; };
// The maximum number of media notifications to count when recording the // The maximum number of media notifications to count when recording the
...@@ -81,6 +86,13 @@ MediaSessionAction GetPlayPauseIgnoredAction( ...@@ -81,6 +86,13 @@ MediaSessionAction GetPlayPauseIgnoredAction(
: MediaSessionAction::kPlay; : MediaSessionAction::kPlay;
} }
MediaSessionAction GetPictureInPictureIgnoredAction(
MediaSessionAction current_action) {
return current_action == MediaSessionAction::kEnterPictureInPicture
? MediaSessionAction::kExitPictureInPicture
: MediaSessionAction::kEnterPictureInPicture;
}
void RecordConcurrentNotificationCount(size_t count) { void RecordConcurrentNotificationCount(size_t count) {
UMA_HISTOGRAM_EXACT_LINEAR(kCountHistogramName, count, UMA_HISTOGRAM_EXACT_LINEAR(kCountHistogramName, count,
kMediaNotificationCountHistogramMax); kMediaNotificationCountHistogramMax);
......
...@@ -49,6 +49,12 @@ COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) ...@@ -49,6 +49,12 @@ COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER)
media_session::mojom::MediaSessionAction GetPlayPauseIgnoredAction( media_session::mojom::MediaSessionAction GetPlayPauseIgnoredAction(
media_session::mojom::MediaSessionAction current_action); media_session::mojom::MediaSessionAction current_action);
// Returns the action on the enter/exit pip toggle button that should be
// ignored when calculating the visible actions.
COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER)
media_session::mojom::MediaSessionAction GetPictureInPictureIgnoredAction(
media_session::mojom::MediaSessionAction current_action);
// Records the concurrent number of media notifications displayed. // Records the concurrent number of media notifications displayed.
COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER)
void RecordConcurrentNotificationCount(size_t count); void RecordConcurrentNotificationCount(size_t count);
......
...@@ -33,16 +33,16 @@ namespace { ...@@ -33,16 +33,16 @@ namespace {
// The number of actions supported when the notification is expanded or not. // The number of actions supported when the notification is expanded or not.
constexpr size_t kMediaNotificationActionsCount = 3; constexpr size_t kMediaNotificationActionsCount = 3;
constexpr size_t kMediaNotificationExpandedActionsCount = 5; constexpr size_t kMediaNotificationExpandedActionsCount = 6;
// Dimensions. // Dimensions.
constexpr int kDefaultMarginSize = 8; constexpr int kDefaultMarginSize = 8;
constexpr int kMediaButtonIconSize = 28; constexpr int kMediaButtonIconSize = 16;
constexpr int kTitleArtistLineHeight = 20; constexpr int kTitleArtistLineHeight = 20;
constexpr double kMediaImageMaxWidthPct = 0.3; constexpr double kMediaImageMaxWidthPct = 0.3;
constexpr double kMediaImageMaxWidthExpandedPct = 0.4; constexpr double kMediaImageMaxWidthExpandedPct = 0.4;
constexpr gfx::Size kMediaButtonSize = gfx::Size(36, 36); constexpr gfx::Size kMediaButtonSize = gfx::Size(36, 36);
constexpr int kMediaButtonRowSeparator = 8; constexpr int kMediaButtonRowSeparator = 0;
constexpr gfx::Insets kMediaTitleArtistInsets = gfx::Insets(8, 8, 0, 8); constexpr gfx::Insets kMediaTitleArtistInsets = gfx::Insets(8, 8, 0, 8);
constexpr gfx::Insets kIconlessMediaNotificationHeaderInsets = constexpr gfx::Insets kIconlessMediaNotificationHeaderInsets =
gfx::Insets(6, 14, 0, 6); gfx::Insets(6, 14, 0, 6);
...@@ -50,6 +50,7 @@ constexpr gfx::Insets kIconMediaNotificationHeaderInsets = ...@@ -50,6 +50,7 @@ constexpr gfx::Insets kIconMediaNotificationHeaderInsets =
gfx::Insets(6, 0, 0, 6); gfx::Insets(6, 0, 0, 6);
constexpr gfx::Size kMediaNotificationButtonRowSize = constexpr gfx::Size kMediaNotificationButtonRowSize =
gfx::Size(124, kMediaButtonSize.height()); gfx::Size(124, kMediaButtonSize.height());
constexpr gfx::Size kPipButtonSeparatorViewSize = gfx::Size(20, 24);
void RecordMetadataHistogram(MediaNotificationViewImpl::Metadata metadata) { void RecordMetadataHistogram(MediaNotificationViewImpl::Metadata metadata) {
UMA_HISTOGRAM_ENUMERATION(MediaNotificationViewImpl::kMetadataHistogramName, UMA_HISTOGRAM_ENUMERATION(MediaNotificationViewImpl::kMetadataHistogramName,
...@@ -70,12 +71,14 @@ const gfx::VectorIcon* GetVectorIconForMediaAction(MediaSessionAction action) { ...@@ -70,12 +71,14 @@ const gfx::VectorIcon* GetVectorIconForMediaAction(MediaSessionAction action) {
return &vector_icons::kMediaSeekForwardIcon; return &vector_icons::kMediaSeekForwardIcon;
case MediaSessionAction::kNextTrack: case MediaSessionAction::kNextTrack:
return &vector_icons::kMediaNextTrackIcon; return &vector_icons::kMediaNextTrackIcon;
case MediaSessionAction::kEnterPictureInPicture:
return &vector_icons::kMediaEnterPipIcon;
case MediaSessionAction::kExitPictureInPicture:
return &vector_icons::kMediaExitPipIcon;
case MediaSessionAction::kStop: case MediaSessionAction::kStop:
case MediaSessionAction::kSkipAd: case MediaSessionAction::kSkipAd:
case MediaSessionAction::kSeekTo: case MediaSessionAction::kSeekTo:
case MediaSessionAction::kScrubTo: case MediaSessionAction::kScrubTo:
case MediaSessionAction::kEnterPictureInPicture:
case MediaSessionAction::kExitPictureInPicture:
NOTREACHED(); NOTREACHED();
break; break;
} }
...@@ -209,6 +212,39 @@ MediaNotificationViewImpl::MediaNotificationViewImpl( ...@@ -209,6 +212,39 @@ MediaNotificationViewImpl::MediaNotificationViewImpl(
l10n_util::GetStringUTF16( l10n_util::GetStringUTF16(
IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_NEXT_TRACK)); IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_NEXT_TRACK));
auto pip_button_separator_view = std::make_unique<views::View>();
auto* pip_button_separator_view_layout =
pip_button_separator_view->SetLayoutManager(
std::make_unique<views::BoxLayout>(
views::BoxLayout::Orientation::kHorizontal, gfx::Insets(), 0));
pip_button_separator_view_layout->set_main_axis_alignment(
views::BoxLayout::MainAxisAlignment::kCenter);
pip_button_separator_view_layout->set_cross_axis_alignment(
views::BoxLayout::CrossAxisAlignment::kCenter);
pip_button_separator_view->SetPreferredSize(kPipButtonSeparatorViewSize);
auto pip_button_separator_stroke = std::make_unique<views::View>();
pip_button_separator_stroke->SetPreferredSize(
gfx::Size(1, kPipButtonSeparatorViewSize.height()));
pip_button_separator_view->AddChildView(
std::move(pip_button_separator_stroke));
pip_button_separator_view_ =
button_row_->AddChildView(std::move(pip_button_separator_view));
auto picture_in_picture_button = views::CreateVectorToggleImageButton(this);
picture_in_picture_button->set_tag(
static_cast<int>(MediaSessionAction::kEnterPictureInPicture));
picture_in_picture_button->SetPreferredSize(kMediaButtonSize);
picture_in_picture_button->SetFocusBehavior(
views::View::FocusBehavior::ALWAYS);
picture_in_picture_button->SetTooltipText(l10n_util::GetStringUTF16(
IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_ENTER_PIP));
picture_in_picture_button->SetToggledTooltipText(l10n_util::GetStringUTF16(
IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_EXIT_PIP));
picture_in_picture_button_ =
button_row_->AddChildView(std::move(picture_in_picture_button));
SetBackground(std::make_unique<MediaNotificationBackground>( SetBackground(std::make_unique<MediaNotificationBackground>(
message_center::kNotificationCornerRadius, message_center::kNotificationCornerRadius,
message_center::kNotificationCornerRadius, kMediaImageMaxWidthPct)); message_center::kNotificationCornerRadius, kMediaImageMaxWidthPct));
...@@ -305,6 +341,16 @@ void MediaNotificationViewImpl::UpdateWithMediaSessionInfo( ...@@ -305,6 +341,16 @@ void MediaNotificationViewImpl::UpdateWithMediaSessionInfo(
playing ? MediaSessionAction::kPause : MediaSessionAction::kPlay; playing ? MediaSessionAction::kPause : MediaSessionAction::kPlay;
play_pause_button_->set_tag(static_cast<int>(action)); play_pause_button_->set_tag(static_cast<int>(action));
bool in_picture_in_picture =
session_info &&
session_info->picture_in_picture_state ==
media_session::mojom::MediaPictureInPictureState::kInPictureInPicture;
picture_in_picture_button_->SetToggled(in_picture_in_picture);
action = in_picture_in_picture ? MediaSessionAction::kExitPictureInPicture
: MediaSessionAction::kEnterPictureInPicture;
picture_in_picture_button_->set_tag(static_cast<int>(action));
UpdateActionButtonsVisibility(); UpdateActionButtonsVisibility();
container_->OnMediaSessionInfoChanged(session_info); container_->OnMediaSessionInfoChanged(session_info);
...@@ -402,13 +448,18 @@ base::string16 MediaNotificationViewImpl::GetSourceTitleForTesting() const { ...@@ -402,13 +448,18 @@ base::string16 MediaNotificationViewImpl::GetSourceTitleForTesting() const {
void MediaNotificationViewImpl::UpdateActionButtonsVisibility() { void MediaNotificationViewImpl::UpdateActionButtonsVisibility() {
base::flat_set<MediaSessionAction> ignored_actions = { base::flat_set<MediaSessionAction> ignored_actions = {
GetPlayPauseIgnoredAction(GetActionFromButtonTag(*play_pause_button_))}; GetPlayPauseIgnoredAction(GetActionFromButtonTag(*play_pause_button_)),
GetPictureInPictureIgnoredAction(
GetActionFromButtonTag(*picture_in_picture_button_))};
base::flat_set<MediaSessionAction> visible_actions = base::flat_set<MediaSessionAction> visible_actions =
GetTopVisibleActions(enabled_actions_, ignored_actions, GetTopVisibleActions(enabled_actions_, ignored_actions,
GetMaxNumActions(IsActuallyExpanded())); GetMaxNumActions(IsActuallyExpanded()));
for (auto* view : button_row_->children()) { for (auto* view : button_row_->children()) {
if (view == pip_button_separator_view_)
continue;
views::Button* action_button = views::Button::AsButton(view); views::Button* action_button = views::Button::AsButton(view);
bool should_show = bool should_show =
base::Contains(visible_actions, GetActionFromButtonTag(*action_button)); base::Contains(visible_actions, GetActionFromButtonTag(*action_button));
...@@ -418,6 +469,13 @@ void MediaNotificationViewImpl::UpdateActionButtonsVisibility() { ...@@ -418,6 +469,13 @@ void MediaNotificationViewImpl::UpdateActionButtonsVisibility() {
if (should_invalidate) if (should_invalidate)
action_button->InvalidateLayout(); action_button->InvalidateLayout();
if (action_button == picture_in_picture_button_) {
pip_button_separator_view_->SetVisible(should_show);
if (should_invalidate)
pip_button_separator_view_->InvalidateLayout();
}
} }
// We want to give the container a list of all possibly visible actions, and // We want to give the container a list of all possibly visible actions, and
...@@ -496,7 +554,9 @@ bool MediaNotificationViewImpl::IsExpandable() const { ...@@ -496,7 +554,9 @@ bool MediaNotificationViewImpl::IsExpandable() const {
return false; return false;
base::flat_set<MediaSessionAction> ignored_actions = { base::flat_set<MediaSessionAction> ignored_actions = {
GetPlayPauseIgnoredAction(GetActionFromButtonTag(*play_pause_button_))}; GetPlayPauseIgnoredAction(GetActionFromButtonTag(*play_pause_button_)),
GetPictureInPictureIgnoredAction(
GetActionFromButtonTag(*picture_in_picture_button_))};
// If we can show more notifications if we were expanded then we should be // If we can show more notifications if we were expanded then we should be
// expandable. // expandable.
...@@ -525,6 +585,9 @@ void MediaNotificationViewImpl::UpdateForegroundColor() { ...@@ -525,6 +585,9 @@ void MediaNotificationViewImpl::UpdateForegroundColor() {
artist_label_->SetBackgroundColor(background); artist_label_->SetBackgroundColor(background);
header_row_->SetBackgroundColor(background); header_row_->SetBackgroundColor(background);
pip_button_separator_view_->children().front()->SetBackground(
views::CreateSolidBackground(foreground));
// Update play/pause button images. // Update play/pause button images.
views::SetImageFromVectorIconWithColor( views::SetImageFromVectorIconWithColor(
play_pause_button_, play_pause_button_,
...@@ -535,12 +598,24 @@ void MediaNotificationViewImpl::UpdateForegroundColor() { ...@@ -535,12 +598,24 @@ void MediaNotificationViewImpl::UpdateForegroundColor() {
*GetVectorIconForMediaAction(MediaSessionAction::kPause), *GetVectorIconForMediaAction(MediaSessionAction::kPause),
kMediaButtonIconSize, foreground); kMediaButtonIconSize, foreground);
views::SetImageFromVectorIconWithColor(
picture_in_picture_button_,
*GetVectorIconForMediaAction(MediaSessionAction::kEnterPictureInPicture),
kMediaButtonIconSize, foreground);
views::SetToggledImageFromVectorIconWithColor(
picture_in_picture_button_,
*GetVectorIconForMediaAction(MediaSessionAction::kExitPictureInPicture),
kMediaButtonIconSize, foreground);
// Update action buttons. // Update action buttons.
for (views::View* child : button_row_->children()) { for (views::View* child : button_row_->children()) {
// Skip the play pause button since it is a special case. // Skip the play pause button since it is a special case.
if (child == play_pause_button_) if (child == play_pause_button_)
continue; continue;
if (child == picture_in_picture_button_)
continue;
// Skip if the view is not an image button. // Skip if the view is not an image button.
if (child->GetClassName() != views::ImageButton::kViewClassName) if (child->GetClassName() != views::ImageButton::kViewClassName)
continue; continue;
......
...@@ -141,7 +141,9 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewImpl ...@@ -141,7 +141,9 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationViewImpl
// Container views directly attached to this view. // Container views directly attached to this view.
message_center::NotificationHeaderView* header_row_ = nullptr; message_center::NotificationHeaderView* header_row_ = nullptr;
views::View* button_row_ = nullptr; views::View* button_row_ = nullptr;
views::View* pip_button_separator_view_ = nullptr;
views::ToggleImageButton* play_pause_button_ = nullptr; views::ToggleImageButton* play_pause_button_ = nullptr;
views::ToggleImageButton* picture_in_picture_button_ = nullptr;
views::View* title_artist_row_ = nullptr; views::View* title_artist_row_ = nullptr;
views::Label* title_label_ = nullptr; views::Label* title_label_ = nullptr;
views::Label* artist_label_ = nullptr; views::Label* artist_label_ = nullptr;
......
...@@ -183,6 +183,8 @@ class MediaNotificationViewImplTest : public views::ViewsTestBase { ...@@ -183,6 +183,8 @@ class MediaNotificationViewImplTest : public views::ViewsTestBase {
actions_.insert(MediaSessionAction::kSeekBackward); actions_.insert(MediaSessionAction::kSeekBackward);
actions_.insert(MediaSessionAction::kSeekForward); actions_.insert(MediaSessionAction::kSeekForward);
actions_.insert(MediaSessionAction::kStop); actions_.insert(MediaSessionAction::kStop);
actions_.insert(MediaSessionAction::kEnterPictureInPicture);
actions_.insert(MediaSessionAction::kExitPictureInPicture);
NotifyUpdatedActions(); NotifyUpdatedActions();
} }
...@@ -232,7 +234,9 @@ class MediaNotificationViewImplTest : public views::ViewsTestBase { ...@@ -232,7 +234,9 @@ class MediaNotificationViewImplTest : public views::ViewsTestBase {
const auto& children = button_row()->children(); const auto& children = button_row()->children();
const auto i = std::find_if( const auto i = std::find_if(
children.begin(), children.end(), [action](const views::View* v) { children.begin(), children.end(), [action](const views::View* v) {
return views::Button::AsButton(v)->tag() == static_cast<int>(action); return (IsMediaButtonType(v->GetClassName()) &&
views::Button::AsButton(v)->tag() ==
static_cast<int>(action));
}); });
return (i == children.end()) ? nullptr : views::Button::AsButton(*i); return (i == children.end()) ? nullptr : views::Button::AsButton(*i);
} }
...@@ -361,10 +365,11 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, ButtonsSanityCheck) { ...@@ -361,10 +365,11 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, ButtonsSanityCheck) {
EXPECT_GT(button_row()->width(), 0); EXPECT_GT(button_row()->width(), 0);
EXPECT_GT(button_row()->height(), 0); EXPECT_GT(button_row()->height(), 0);
EXPECT_EQ(5u, button_row()->children().size()); EXPECT_EQ(7u, button_row()->children().size());
for (auto* child : button_row()->children()) { for (auto* child : button_row()->children()) {
ASSERT_TRUE(IsMediaButtonType(child->GetClassName())); if (!IsMediaButtonType(child->GetClassName()))
continue;
EXPECT_TRUE(child->GetVisible()); EXPECT_TRUE(child->GetVisible());
EXPECT_LT(kMediaButtonIconSize, child->width()); EXPECT_LT(kMediaButtonIconSize, child->width());
...@@ -377,9 +382,11 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, ButtonsSanityCheck) { ...@@ -377,9 +382,11 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, ButtonsSanityCheck) {
EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kNextTrack)); EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kNextTrack));
EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kSeekBackward)); EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kSeekBackward));
EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kSeekForward)); EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kSeekForward));
EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kEnterPictureInPicture));
// |kPause| cannot be present if |kPlay| is. // |kPause| cannot be present if |kPlay| is.
EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause)); EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause));
EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kExitPictureInPicture));
} }
#if defined(OS_WIN) #if defined(OS_WIN)
...@@ -679,7 +686,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) { ...@@ -679,7 +686,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) {
OnVisibleActionsChanged(base::flat_set<MediaSessionAction>( OnVisibleActionsChanged(base::flat_set<MediaSessionAction>(
{MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward, MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
MediaSessionAction::kSeekForward}))); MediaSessionAction::kSeekForward,
MediaSessionAction::kEnterPictureInPicture})));
EnableAllActions(); EnableAllActions();
view()->SetExpanded(false); view()->SetExpanded(false);
testing::Mock::VerifyAndClearExpectations(&container()); testing::Mock::VerifyAndClearExpectations(&container());
...@@ -696,7 +704,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) { ...@@ -696,7 +704,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) {
container(), container(),
OnVisibleActionsChanged(base::flat_set<MediaSessionAction>( OnVisibleActionsChanged(base::flat_set<MediaSessionAction>(
{MediaSessionAction::kPlay, MediaSessionAction::kSeekBackward, {MediaSessionAction::kPlay, MediaSessionAction::kSeekBackward,
MediaSessionAction::kNextTrack, MediaSessionAction::kSeekForward}))); MediaSessionAction::kNextTrack, MediaSessionAction::kSeekForward,
MediaSessionAction::kEnterPictureInPicture})));
DisableAction(MediaSessionAction::kPreviousTrack); DisableAction(MediaSessionAction::kPreviousTrack);
testing::Mock::VerifyAndClearExpectations(&container()); testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack));
...@@ -706,7 +715,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) { ...@@ -706,7 +715,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) {
OnVisibleActionsChanged(base::flat_set<MediaSessionAction>( OnVisibleActionsChanged(base::flat_set<MediaSessionAction>(
{MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward, MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
MediaSessionAction::kSeekForward}))); MediaSessionAction::kSeekForward,
MediaSessionAction::kEnterPictureInPicture})));
EnableAction(MediaSessionAction::kPreviousTrack); EnableAction(MediaSessionAction::kPreviousTrack);
testing::Mock::VerifyAndClearExpectations(&container()); testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack));
...@@ -715,8 +725,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) { ...@@ -715,8 +725,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) {
container(), container(),
OnVisibleActionsChanged(base::flat_set<MediaSessionAction>( OnVisibleActionsChanged(base::flat_set<MediaSessionAction>(
{MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
MediaSessionAction::kNextTrack, MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
MediaSessionAction::kSeekBackward}))); MediaSessionAction::kEnterPictureInPicture})));
DisableAction(MediaSessionAction::kSeekForward); DisableAction(MediaSessionAction::kSeekForward);
testing::Mock::VerifyAndClearExpectations(&container()); testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward));
...@@ -726,7 +736,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) { ...@@ -726,7 +736,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenCollapsed) {
OnVisibleActionsChanged(base::flat_set<MediaSessionAction>( OnVisibleActionsChanged(base::flat_set<MediaSessionAction>(
{MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward, MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
MediaSessionAction::kSeekForward}))); MediaSessionAction::kSeekForward,
MediaSessionAction::kEnterPictureInPicture})));
EnableAction(MediaSessionAction::kSeekForward); EnableAction(MediaSessionAction::kSeekForward);
testing::Mock::VerifyAndClearExpectations(&container()); testing::Mock::VerifyAndClearExpectations(&container());
EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward));
...@@ -738,7 +749,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenExpanded) { ...@@ -738,7 +749,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenExpanded) {
OnVisibleActionsChanged(base::flat_set<MediaSessionAction>( OnVisibleActionsChanged(base::flat_set<MediaSessionAction>(
{MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward, MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
MediaSessionAction::kSeekForward}))); MediaSessionAction::kSeekForward,
MediaSessionAction::kEnterPictureInPicture})));
EnableAllActions(); EnableAllActions();
testing::Mock::VerifyAndClearExpectations(&container()); testing::Mock::VerifyAndClearExpectations(&container());
...@@ -747,7 +759,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenExpanded) { ...@@ -747,7 +759,8 @@ TEST_F(MAYBE_MediaNotificationViewImplTest, Buttons_WhenExpanded) {
OnVisibleActionsChanged(base::flat_set<MediaSessionAction>( OnVisibleActionsChanged(base::flat_set<MediaSessionAction>(
{MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack,
MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward, MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward,
MediaSessionAction::kSeekForward}))); MediaSessionAction::kSeekForward,
MediaSessionAction::kEnterPictureInPicture})));
view()->SetExpanded(true); view()->SetExpanded(true);
testing::Mock::VerifyAndClearExpectations(&container()); testing::Mock::VerifyAndClearExpectations(&container());
......
...@@ -18,6 +18,12 @@ ...@@ -18,6 +18,12 @@
<message name="IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_NEXT_TRACK" desc="The button to trigger media playback to go to the next track."> <message name="IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_NEXT_TRACK" desc="The button to trigger media playback to go to the next track.">
Next Track Next Track
</message> </message>
<message name="IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_ENTER_PIP" desc="The button to trigeer media playback to go in pip mode.">
Enter picture-in-picture
</message>
<message name="IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACTION_EXIT_PIP" desc="The button to trigeer media playback to exit pip mode.">
Exit picture-in-picture
</message>
<message name="IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACCESSIBLE_NAME" desc="The accessible name for the media notification to control playback."> <message name="IDS_MEDIA_MESSAGE_CENTER_MEDIA_NOTIFICATION_ACCESSIBLE_NAME" desc="The accessible name for the media notification to control playback.">
Media Controls Media Controls
</message> </message>
......
...@@ -43,6 +43,8 @@ aggregate_vector_icons("components_vector_icons") { ...@@ -43,6 +43,8 @@ aggregate_vector_icons("components_vector_icons") {
"media_router_warning.icon", "media_router_warning.icon",
"media_seek_backward.icon", "media_seek_backward.icon",
"media_seek_forward.icon", "media_seek_forward.icon",
"media_enter_pip.icon",
"media_exit_pip.icon",
"mic.icon", "mic.icon",
"midi.icon", "midi.icon",
"notifications.icon", "notifications.icon",
......
// 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.
CANVAS_DIMENSIONS, 32,
MOVE_TO, 24, 14,
H_LINE_TO, 14,
R_V_LINE_TO, 8,
R_H_LINE_TO, 10,
R_V_LINE_TO, -8,
CLOSE,
R_MOVE_TO, 4, 9.78f,
V_LINE_TO, 8.2f,
ARC_TO, 2.19f, 2.19f, 0, 0, 0, 25.82f, 6,
H_LINE_TO, 6.18f,
ARC_TO, 2.19f, 2.19f, 0, 0, 0, 4, 8.2f,
R_V_LINE_TO, 15.58f,
CUBIC_TO, 4, 25, 4.98f, 26, 6.18f, 26,
R_H_LINE_TO, 19.64f,
R_CUBIC_TO, 1.2f, 0, 2.18f, -1, 2.18f, -2.22f,
CLOSE,
MOVE_TO, 26, 24,
H_LINE_TO, 6,
V_LINE_TO, 8,
R_H_LINE_TO, 20,
R_V_LINE_TO, 16,
CLOSE
// 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.
CANVAS_DIMENSIONS, 32,
MOVE_TO, 25.82f, 6,
CUBIC_TO, 27.02f, 6, 28, 6.98f, 28, 8.2f,
V_LINE_TO, 16,
R_H_LINE_TO, -2,
V_LINE_TO, 8,
H_LINE_TO, 6,
R_V_LINE_TO, 16,
R_H_LINE_TO, 12,
R_V_LINE_TO, 2,
H_LINE_TO, 6.18f,
CUBIC_TO, 4.98f, 26, 4, 25, 4, 23.78f,
V_LINE_TO, 8.2f,
CUBIC_TO, 4, 6.98f, 4.98f, 6, 6.18f, 6,
CLOSE,
MOVE_TO, 18, 10,
H_LINE_TO, 8,
R_V_LINE_TO, 8,
R_H_LINE_TO, 10,
CLOSE,
MOVE_TO, 22, 18,
R_V_LINE_TO, 8,
R_H_LINE_TO, -2,
R_V_LINE_TO, -8,
CLOSE,
MOVE_TO, 21.41f, 18,
R_LINE_TO, 8.49f, 8.49f,
R_LINE_TO, -1.41f, 1.41f,
LINE_TO, 20, 19.41f,
CLOSE,
MOVE_TO, 21, 18,
R_H_LINE_TO, 7,
R_V_LINE_TO, 2,
R_H_LINE_TO, -7,
CLOSE
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "content/public/common/content_client.h" #include "content/public/common/content_client.h"
#include "content/public/common/favicon_url.h" #include "content/public/common/favicon_url.h"
#include "media/base/media_content_type.h" #include "media/base/media_content_type.h"
#include "media/base/media_switches.h"
#include "mojo/public/cpp/bindings/callback_helpers.h" #include "mojo/public/cpp/bindings/callback_helpers.h"
#include "services/media_session/public/cpp/media_image_manager.h" #include "services/media_session/public/cpp/media_image_manager.h"
#include "services/media_session/public/mojom/audio_focus.mojom.h" #include "services/media_session/public/mojom/audio_focus.mojom.h"
...@@ -1363,7 +1364,9 @@ void MediaSessionImpl::RebuildAndNotifyActionsChanged() { ...@@ -1363,7 +1364,9 @@ void MediaSessionImpl::RebuildAndNotifyActionsChanged() {
actions.insert(media_session::mojom::MediaSessionAction::kStop); actions.insert(media_session::mojom::MediaSessionAction::kStop);
} }
if (IsPictureInPictureAvailable()) { if (base::FeatureList::IsEnabled(
media::kGlobalMediaControlsPictureInPicture) &&
IsPictureInPictureAvailable()) {
actions.insert( actions.insert(
media_session::mojom::MediaSessionAction::kEnterPictureInPicture); media_session::mojom::MediaSessionAction::kEnterPictureInPicture);
actions.insert( actions.insert(
......
...@@ -352,6 +352,10 @@ const base::Feature kGlobalMediaControlsForCast{ ...@@ -352,6 +352,10 @@ const base::Feature kGlobalMediaControlsForCast{
const base::Feature kGlobalMediaControlsOverlayControls{ const base::Feature kGlobalMediaControlsOverlayControls{
"GlobalMediaControlsOverlayControls", base::FEATURE_DISABLED_BY_DEFAULT}; "GlobalMediaControlsOverlayControls", base::FEATURE_DISABLED_BY_DEFAULT};
// Show picture-in-picture button in Global Media Controls.
const base::Feature kGlobalMediaControlsPictureInPicture{
"GlobalMediaControlsPictureInPicture", base::FEATURE_DISABLED_BY_DEFAULT};
// Enable new cpu load estimator. Intended for evaluation in local // Enable new cpu load estimator. Intended for evaluation in local
// testing and origin-trial. // testing and origin-trial.
// TODO(nisse): Delete once we have switched over to always using the // TODO(nisse): Delete once we have switched over to always using the
......
...@@ -122,6 +122,7 @@ MEDIA_EXPORT extern const base::Feature kGlobalMediaControls; ...@@ -122,6 +122,7 @@ MEDIA_EXPORT extern const base::Feature kGlobalMediaControls;
MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsAutoDismiss; MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsAutoDismiss;
MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsForCast; MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsForCast;
MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsOverlayControls; MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsOverlayControls;
MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsPictureInPicture;
MEDIA_EXPORT extern const base::Feature kHardwareMediaKeyHandling; MEDIA_EXPORT extern const base::Feature kHardwareMediaKeyHandling;
MEDIA_EXPORT extern const base::Feature kHardwareSecureDecryption; MEDIA_EXPORT extern const base::Feature kHardwareSecureDecryption;
MEDIA_EXPORT extern const base::Feature kInternalMediaSession; MEDIA_EXPORT extern const base::Feature kInternalMediaSession;
......
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