diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-01-23 17:21:03 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-01-23 16:25:15 +0000 |
commit | c551f43206405019121bd2b2c93714319a0a3300 (patch) | |
tree | 1f48c30631c421fd4bbb3c36da20183c8a2ed7d7 /chromium/components/media_message_center | |
parent | 7961cea6d1041e3e454dae6a1da660b453efd238 (diff) | |
download | qtwebengine-chromium-c551f43206405019121bd2b2c93714319a0a3300.tar.gz |
BASELINE: Update Chromium to 79.0.3945.139
Change-Id: I336b7182fab9bca80b709682489c07db112eaca5
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/media_message_center')
12 files changed, 502 insertions, 125 deletions
diff --git a/chromium/components/media_message_center/OWNERS b/chromium/components/media_message_center/OWNERS index e4ffdff85c0..15cde728ed3 100644 --- a/chromium/components/media_message_center/OWNERS +++ b/chromium/components/media_message_center/OWNERS @@ -1,2 +1,5 @@ beccahughes@chromium.org steimel@chromium.org + +# COMPONENT: UI>Notifications +# TEAM: media-dev@chromium.org diff --git a/chromium/components/media_message_center/media_controls_progress_view.cc b/chromium/components/media_message_center/media_controls_progress_view.cc index af87e06f8f3..44cda878638 100644 --- a/chromium/components/media_message_center/media_controls_progress_view.cc +++ b/chromium/components/media_message_center/media_controls_progress_view.cc @@ -6,6 +6,7 @@ #include "base/i18n/time_formatting.h" #include "services/media_session/public/mojom/media_session.mojom.h" +#include "ui/gfx/color_palette.h" #include "ui/gfx/font_list.h" #include "ui/views/border.h" #include "ui/views/controls/label.h" @@ -19,7 +20,8 @@ namespace media_message_center { namespace { -constexpr int kProgressBarAndTimeSpacing = 3; +constexpr SkColor kTimeColor = gfx::kGoogleGrey200; +constexpr int kProgressBarAndTimeSpacing = 8; constexpr int kProgressTimeFontSize = 11; constexpr int kProgressBarHeight = 4; constexpr int kMinClickHeight = 14; @@ -56,7 +58,7 @@ MediaControlsProgressView::MediaControlsProgressView( auto progress_time = std::make_unique<views::Label>(); progress_time->SetFontList(font_list); - progress_time->SetEnabledColor(SK_ColorWHITE); + progress_time->SetEnabledColor(kTimeColor); progress_time->SetAutoColorReadabilityEnabled(false); progress_time_ = time_view->AddChildView(std::move(progress_time)); @@ -130,6 +132,14 @@ void MediaControlsProgressView::UpdateProgress( } } +void MediaControlsProgressView::SetForegroundColor(SkColor color) { + progress_bar_->SetForegroundColor(color); +} + +void MediaControlsProgressView::SetBackgroundColor(SkColor color) { + progress_bar_->SetBackgroundColor(color); +} + bool MediaControlsProgressView::OnMousePressed(const ui::MouseEvent& event) { if (!event.IsOnlyLeftMouseButton() || event.y() < kMinClickHeight || event.y() > kMaxClickHeight) { diff --git a/chromium/components/media_message_center/media_controls_progress_view.h b/chromium/components/media_message_center/media_controls_progress_view.h index 8f5ac64c5a1..9c986568d49 100644 --- a/chromium/components/media_message_center/media_controls_progress_view.h +++ b/chromium/components/media_message_center/media_controls_progress_view.h @@ -25,6 +25,9 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaControlsProgressView void UpdateProgress(const media_session::MediaPosition& media_position); + void SetForegroundColor(SkColor color); + void SetBackgroundColor(SkColor color); + // views::View: bool OnMousePressed(const ui::MouseEvent& event) override; void OnGestureEvent(ui::GestureEvent* event) override; diff --git a/chromium/components/media_message_center/media_controls_progress_view_unittest.cc b/chromium/components/media_message_center/media_controls_progress_view_unittest.cc index 5d5e89e1343..9f791ca37f3 100644 --- a/chromium/components/media_message_center/media_controls_progress_view_unittest.cc +++ b/chromium/components/media_message_center/media_controls_progress_view_unittest.cc @@ -54,7 +54,17 @@ class MediaControlsProgressViewTest : public views::ViewsTestBase { DISALLOW_COPY_AND_ASSIGN(MediaControlsProgressViewTest); }; -TEST_F(MediaControlsProgressViewTest, InitProgress) { +// TODO(crbug.com/1009356): many of these tests are failing on TSan builds. +#if defined(THREAD_SANITIZER) +#define MAYBE_MediaControlsProgressViewTest \ + DISABLED_MediaControlsProgressViewTest +class DISABLED_MediaControlsProgressViewTest + : public MediaControlsProgressViewTest {}; +#else +#define MAYBE_MediaControlsProgressViewTest MediaControlsProgressViewTest +#endif + +TEST_F(MAYBE_MediaControlsProgressViewTest, InitProgress) { media_session::MediaPosition media_position( 1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */, base::TimeDelta::FromSeconds(300) /* position */); @@ -65,10 +75,10 @@ TEST_F(MediaControlsProgressViewTest, InitProgress) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); } -TEST_F(MediaControlsProgressViewTest, InitProgressOverHour) { +TEST_F(MAYBE_MediaControlsProgressViewTest, InitProgressOverHour) { media_session::MediaPosition media_position( 1 /* playback_rate */, base::TimeDelta::FromHours(2) /* duration */, base::TimeDelta::FromMinutes(30) /* position */); @@ -79,10 +89,10 @@ TEST_F(MediaControlsProgressViewTest, InitProgressOverHour) { base::ASCIIToUTF16("2:00:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("0:30:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .25); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .25); } -TEST_F(MediaControlsProgressViewTest, InitProgressOverDay) { +TEST_F(MAYBE_MediaControlsProgressViewTest, InitProgressOverDay) { media_session::MediaPosition media_position( 1 /* playback_rate */, base::TimeDelta::FromHours(25) /* duration */, base::TimeDelta::FromHours(5) /* position */); @@ -94,10 +104,10 @@ TEST_F(MediaControlsProgressViewTest, InitProgressOverDay) { base::ASCIIToUTF16("25h 0m 0s")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("5h 0m 0s")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .2); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .2); } -TEST_F(MediaControlsProgressViewTest, UpdateProgress) { +TEST_F(MAYBE_MediaControlsProgressViewTest, UpdateProgress) { media_session::MediaPosition media_position( 1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */, base::TimeDelta::FromSeconds(300) /* position */); @@ -108,7 +118,7 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgress) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); task_environment_->FastForwardBy(base::TimeDelta::FromSeconds(30)); task_environment_->RunUntilIdle(); @@ -117,10 +127,10 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgress) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:30")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .55); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .55); } -TEST_F(MediaControlsProgressViewTest, UpdateProgressFastPlayback) { +TEST_F(MAYBE_MediaControlsProgressViewTest, UpdateProgressFastPlayback) { media_session::MediaPosition media_position( 2 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */, base::TimeDelta::FromSeconds(300) /* position */); @@ -131,7 +141,7 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressFastPlayback) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); task_environment_->FastForwardBy(base::TimeDelta::FromSeconds(15)); task_environment_->RunUntilIdle(); @@ -140,10 +150,10 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressFastPlayback) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:30")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .55); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .55); } -TEST_F(MediaControlsProgressViewTest, UpdateProgressSlowPlayback) { +TEST_F(MAYBE_MediaControlsProgressViewTest, UpdateProgressSlowPlayback) { media_session::MediaPosition media_position( .5 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */, base::TimeDelta::FromSeconds(300) /* position */); @@ -154,7 +164,7 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressSlowPlayback) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); task_environment_->FastForwardBy(base::TimeDelta::FromSeconds(60)); task_environment_->RunUntilIdle(); @@ -163,10 +173,10 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressSlowPlayback) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:30")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .55); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .55); } -TEST_F(MediaControlsProgressViewTest, UpdateProgressNegativePlayback) { +TEST_F(MAYBE_MediaControlsProgressViewTest, UpdateProgressNegativePlayback) { media_session::MediaPosition media_position( -1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */, base::TimeDelta::FromSeconds(300) /* position */); @@ -177,7 +187,7 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressNegativePlayback) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); task_environment_->FastForwardBy(base::TimeDelta::FromSeconds(30)); task_environment_->RunUntilIdle(); @@ -186,10 +196,10 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressNegativePlayback) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("04:30")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .45); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .45); } -TEST_F(MediaControlsProgressViewTest, UpdateProgressPastDuration) { +TEST_F(MAYBE_MediaControlsProgressViewTest, UpdateProgressPastDuration) { media_session::MediaPosition media_position( 1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */, base::TimeDelta::FromSeconds(300) /* position */); @@ -200,7 +210,7 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressPastDuration) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); // Move forward in time past the duration. task_environment_->FastForwardBy(base::TimeDelta::FromMinutes(6)); @@ -211,10 +221,10 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressPastDuration) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("10:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), 1); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), 1); } -TEST_F(MediaControlsProgressViewTest, UpdateProgressBeforeStart) { +TEST_F(MAYBE_MediaControlsProgressViewTest, UpdateProgressBeforeStart) { media_session::MediaPosition media_position( -1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */, base::TimeDelta::FromSeconds(300) /* position */); @@ -225,7 +235,7 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressBeforeStart) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); // Move forward in time before the start using negative playback rate. task_environment_->FastForwardBy(base::TimeDelta::FromMinutes(6)); @@ -236,10 +246,10 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressBeforeStart) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("00:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), 0); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), 0); } -TEST_F(MediaControlsProgressViewTest, UpdateProgressPaused) { +TEST_F(MAYBE_MediaControlsProgressViewTest, UpdateProgressPaused) { media_session::MediaPosition media_position( 0 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */, base::TimeDelta::FromSeconds(300) /* position */); @@ -250,7 +260,7 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressPaused) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); task_environment_->FastForwardBy(base::TimeDelta::FromMinutes(6)); task_environment_->RunUntilIdle(); @@ -260,10 +270,10 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressPaused) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); } -TEST_F(MediaControlsProgressViewTest, UpdateProgressTwice) { +TEST_F(MAYBE_MediaControlsProgressViewTest, UpdateProgressTwice) { media_session::MediaPosition media_position( 1 /* playback_rate */, base::TimeDelta::FromSeconds(600) /* duration */, base::TimeDelta::FromSeconds(300) /* position */); @@ -275,7 +285,7 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressTwice) { base::ASCIIToUTF16("10:00")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("05:00")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .5); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .5); media_session::MediaPosition new_media_position( 1 /* playback_rate */, base::TimeDelta::FromSeconds(200) /* duration */, @@ -289,7 +299,7 @@ TEST_F(MediaControlsProgressViewTest, UpdateProgressTwice) { base::ASCIIToUTF16("03:20")); EXPECT_EQ(progress_view_->progress_time_for_testing(), base::ASCIIToUTF16("00:50")); - EXPECT_EQ(progress_view_->progress_bar_for_testing()->current_value(), .25); + EXPECT_EQ(progress_view_->progress_bar_for_testing()->GetValue(), .25); } } // namespace media_message_center diff --git a/chromium/components/media_message_center/media_notification_background_unittest.cc b/chromium/components/media_message_center/media_notification_background_unittest.cc index e9293374110..53712fe32cb 100644 --- a/chromium/components/media_message_center/media_notification_background_unittest.cc +++ b/chromium/components/media_message_center/media_notification_background_unittest.cc @@ -140,7 +140,7 @@ TEST_F(MediaNotificationBackgroundTest, TEST_F(MediaNotificationBackgroundTest, GetBackgroundColorRespectsTheme) { TestDarkTheme dark_theme; views::View owner; - owner.SetNativeTheme(&dark_theme); + owner.SetNativeThemeForTesting(&dark_theme); EXPECT_EQ(kDarkBackgroundColor, background()->GetBackgroundColor(owner)); } diff --git a/chromium/components/media_message_center/media_notification_container.h b/chromium/components/media_message_center/media_notification_container.h index 63a5cd32fd4..b4d2887b79d 100644 --- a/chromium/components/media_message_center/media_notification_container.h +++ b/chromium/components/media_message_center/media_notification_container.h @@ -24,6 +24,13 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationContainer { // Called when MediaNotificationView's expanded state changes. virtual void OnExpanded(bool expanded) = 0; + // Called when the MediaSessionInfo changes. + virtual void OnMediaSessionInfoChanged( + const media_session::mojom::MediaSessionInfoPtr& session_info) = 0; + + // Called when the metadata changes. + virtual void OnMediaSessionMetadataChanged() = 0; + // TODO(https://crbug.com/1003847): Use base::flat_set isntead. // Called when the set of visible MediaSessionActions changes. virtual void OnVisibleActionsChanged( @@ -31,6 +38,15 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationContainer { // Called when the media artwork changes. virtual void OnMediaArtworkChanged(const gfx::ImageSkia& image) = 0; + + // Called when MediaNotificationView's colors change. + virtual void OnColorsChanged(SkColor foreground, SkColor background) = 0; + + // Called when the header row is clicked. + virtual void OnHeaderClicked() = 0; + + protected: + virtual ~MediaNotificationContainer() = default; }; } // namespace media_message_center diff --git a/chromium/components/media_message_center/media_notification_controller.h b/chromium/components/media_message_center/media_notification_controller.h index 86467d65a68..7fdbcdb5bfc 100644 --- a/chromium/components/media_message_center/media_notification_controller.h +++ b/chromium/components/media_message_center/media_notification_controller.h @@ -38,6 +38,9 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationController { // Notifies the MediaNotificationController that a media button was pressed on // the MediaNotificationView. virtual void LogMediaSessionActionButtonPressed(const std::string& id) = 0; + + protected: + virtual ~MediaNotificationController() = default; }; } // namespace media_message_center diff --git a/chromium/components/media_message_center/media_notification_item.cc b/chromium/components/media_message_center/media_notification_item.cc index 0c89f90135a..9c69d707688 100644 --- a/chromium/components/media_message_center/media_notification_item.cc +++ b/chromium/components/media_message_center/media_notification_item.cc @@ -124,6 +124,8 @@ void MediaNotificationItem::MediaControllerImageChanged( if (view_ && !frozen_) view_->UpdateWithMediaArtwork(*session_artwork_); + else if (waiting_for_artwork_) + MaybeUnfreeze(); } void MediaNotificationItem::SetView(MediaNotificationView* view) { @@ -162,6 +164,13 @@ bool MediaNotificationItem::ShouldShowNotification() const { void MediaNotificationItem::OnFreezeTimerFired() { DCHECK(frozen_); + // If we've just been waiting for artwork, stop waiting and just show what we + // have. + if (waiting_for_artwork_ && ShouldShowNotification() && is_bound_) { + Unfreeze(); + return; + } + if (is_bound_) { controller_->HideNotification(request_id_); } else { @@ -225,12 +234,20 @@ void MediaNotificationItem::SetController( MaybeHideOrShowNotification(); } +void MediaNotificationItem::Dismiss() { + if (media_controller_remote_.is_bound()) + media_controller_remote_->Stop(); + controller_->RemoveItem(request_id_); +} + void MediaNotificationItem::Freeze() { + is_bound_ = false; + if (frozen_) return; frozen_ = true; - is_bound_ = false; + frozen_with_artwork_ = HasArtwork(); freeze_timer_.Start(FROM_HERE, kFreezeTimerDelay, base::BindOnce(&MediaNotificationItem::OnFreezeTimerFired, @@ -241,10 +258,27 @@ void MediaNotificationItem::MaybeUnfreeze() { if (!frozen_) return; + if (waiting_for_artwork_ && !HasArtwork()) + return; + if (!ShouldShowNotification() || !is_bound_) return; + // If the currently frozen view has artwork and the new session currently has + // no artwork, then wait until either the freeze timer ends or the new artwork + // is downloaded. + if (frozen_with_artwork_ && !HasArtwork()) { + waiting_for_artwork_ = true; + return; + } + + Unfreeze(); +} + +void MediaNotificationItem::Unfreeze() { frozen_ = false; + waiting_for_artwork_ = false; + frozen_with_artwork_ = false; freeze_timer_.Stop(); // When we unfreeze, we want to fully update |view_| with any changes that @@ -260,4 +294,8 @@ void MediaNotificationItem::MaybeUnfreeze() { } } +bool MediaNotificationItem::HasArtwork() const { + return session_artwork_.has_value() && !session_artwork_->isNull(); +} + } // namespace media_message_center diff --git a/chromium/components/media_message_center/media_notification_item.h b/chromium/components/media_message_center/media_notification_item.h index 63f91cbceb6..b442fcecc2f 100644 --- a/chromium/components/media_message_center/media_notification_item.h +++ b/chromium/components/media_message_center/media_notification_item.h @@ -92,6 +92,10 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationItem mojo::Remote<media_session::mojom::MediaController> controller, media_session::mojom::MediaSessionInfoPtr session_info); + // This will stop the media session associated with this item. The item will + // then call |MediaNotificationController::RemoveItem()| to ensure removal. + void Dismiss(); + // This will freeze the item and start a timer to destroy the item after // some time has passed. void Freeze(); @@ -103,6 +107,10 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationItem void MaybeUnfreeze(); + void Unfreeze(); + + bool HasArtwork() const; + void OnFreezeTimerFired(); void MaybeHideOrShowNotification(); @@ -141,6 +149,14 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationItem // data and no actions will be executed. bool frozen_ = false; + // True if we're currently frozen and the frozen view contains non-null + // artwork. + bool frozen_with_artwork_ = false; + + // True if we have the necessary metadata to unfreeze, but we're waiting for + // new artwork to load. + bool waiting_for_artwork_ = false; + // The timer that will notify the controller to destroy this item after it // has been frozen for a certain period of time. base::OneShotTimer freeze_timer_; diff --git a/chromium/components/media_message_center/media_notification_view.cc b/chromium/components/media_message_center/media_notification_view.cc index 6ac5e90fb6f..40ec2c83c41 100644 --- a/chromium/components/media_message_center/media_notification_view.cc +++ b/chromium/components/media_message_center/media_notification_view.cc @@ -14,11 +14,11 @@ #include "components/strings/grit/components_strings.h" #include "components/vector_icons/vector_icons.h" #include "services/media_session/public/mojom/media_session.mojom.h" +#include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/font.h" #include "ui/gfx/font_list.h" -#include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/message_center/views/notification_header_view.h" #include "ui/views/controls/button/image_button_factory.h" #include "ui/views/layout/box_layout.h" @@ -31,13 +31,6 @@ using media_session::mojom::MediaSessionAction; namespace { -// The right padding is 1/5th the size of the notification. -constexpr int kRightMarginSize = message_center::kNotificationWidth / 5; - -// The right padding is 1/3rd the size of the notification when the -// notification is expanded. -constexpr int kRightMarginExpandedSize = message_center::kNotificationWidth / 4; - // The number of actions supported when the notification is expanded or not. constexpr size_t kMediaNotificationActionsCount = 3; constexpr size_t kMediaNotificationExpandedActionsCount = 5; @@ -51,9 +44,10 @@ constexpr double kMediaImageMaxWidthExpandedPct = 0.4; constexpr gfx::Size kMediaButtonSize = gfx::Size(36, 36); constexpr int kMediaButtonRowSeparator = 8; constexpr gfx::Insets kMediaTitleArtistInsets = gfx::Insets(8, 8, 0, 8); -constexpr int kMediaNotificationHeaderTopInset = 6; -constexpr int kMediaNotificationHeaderRightInset = 6; -constexpr int kMediaNotificationHeaderInset = 0; +constexpr gfx::Insets kIconlessMediaNotificationHeaderInsets = + gfx::Insets(6, 14, 0, 6); +constexpr gfx::Insets kIconMediaNotificationHeaderInsets = + gfx::Insets(6, 0, 0, 6); constexpr gfx::Size kMediaNotificationButtonRowSize = gfx::Size(124, kMediaButtonSize.height()); @@ -106,11 +100,14 @@ MediaNotificationView::MediaNotificationView( MediaNotificationContainer* container, base::WeakPtr<MediaNotificationItem> item, views::View* header_row_controls_view, - const base::string16& default_app_name) + const base::string16& default_app_name, + int notification_width, + bool should_show_icon) : container_(container), item_(std::move(item)), header_row_controls_view_(header_row_controls_view), - default_app_name_(default_app_name) { + default_app_name_(default_app_name), + notification_width_(notification_width) { DCHECK(container_); SetLayoutManager(std::make_unique<views::BoxLayout>( @@ -123,12 +120,17 @@ MediaNotificationView::MediaNotificationView( header_row->AddChildView(header_row_controls_view_); header_row->SetAppName(default_app_name_); - header_row->ClearAppIcon(); - header_row->SetProperty( - views::kMarginsKey, - gfx::Insets(kMediaNotificationHeaderTopInset, - kMediaNotificationHeaderInset, kMediaNotificationHeaderInset, - kMediaNotificationHeaderRightInset)); + + if (should_show_icon) { + header_row->ClearAppIcon(); + header_row->SetProperty(views::kMarginsKey, + kIconMediaNotificationHeaderInsets); + } else { + header_row->HideAppIcon(); + header_row->SetProperty(views::kMarginsKey, + kIconlessMediaNotificationHeaderInsets); + } + header_row_ = AddChildView(std::move(header_row)); // |main_row_| holds the main content of the notification. @@ -154,12 +156,14 @@ MediaNotificationView::MediaNotificationView( title_label->SetFontList(base_font_list.Derive( 0, gfx::Font::FontStyle::NORMAL, gfx::Font::Weight::MEDIUM)); title_label->SetLineHeight(kTitleArtistLineHeight); + title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); title_label_ = title_artist_row_->AddChildView(std::move(title_label)); auto artist_label = std::make_unique<views::Label>( base::string16(), views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY); artist_label->SetLineHeight(kTitleArtistLineHeight); + artist_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); artist_label_ = title_artist_row_->AddChildView(std::move(artist_label)); // |button_row_| contains the buttons for controlling playback. @@ -272,6 +276,7 @@ void MediaNotificationView::ButtonPressed(views::Button* sender, const ui::Event& event) { if (sender == header_row_) { SetExpanded(!expanded_); + container_->OnHeaderClicked(); return; } @@ -298,6 +303,8 @@ void MediaNotificationView::UpdateWithMediaSessionInfo( UpdateActionButtonsVisibility(); + container_->OnMediaSessionInfoChanged(session_info); + PreferredSizeChanged(); Layout(); SchedulePaint(); @@ -314,17 +321,31 @@ void MediaNotificationView::UpdateWithMediaMetadata( accessible_name_ = GetAccessibleNameFromMetadata(metadata); - if (!metadata.title.empty()) + // The title label should only be a11y-focusable when there is text to be + // read. + if (metadata.title.empty()) { + title_label_->SetFocusBehavior(FocusBehavior::NEVER); + } else { + title_label_->SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); RecordMetadataHistogram(Metadata::kTitle); + } - if (!metadata.artist.empty()) + // The artist label should only be a11y-focusable when there is text to be + // read. + if (metadata.artist.empty()) { + artist_label_->SetFocusBehavior(FocusBehavior::NEVER); + } else { + artist_label_->SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY); RecordMetadataHistogram(Metadata::kArtist); + } if (!metadata.album.empty()) RecordMetadataHistogram(Metadata::kAlbum); RecordMetadataHistogram(Metadata::kCount); + container_->OnMediaSessionMetadataChanged(); + PreferredSizeChanged(); Layout(); SchedulePaint(); @@ -360,6 +381,10 @@ void MediaNotificationView::UpdateWithMediaArtwork( SchedulePaint(); } +views::Button* MediaNotificationView::GetHeaderRowForTesting() const { + return header_row_; +} + void MediaNotificationView::UpdateActionButtonsVisibility() { std::set<MediaSessionAction> ignored_actions = { GetPlayPauseIgnoredAction(GetActionFromButtonTag(*play_pause_button_))}; @@ -380,7 +405,11 @@ void MediaNotificationView::UpdateActionButtonsVisibility() { action_button->InvalidateLayout(); } - container_->OnVisibleActionsChanged(visible_actions); + // We want to give the container a list of all possibly visible actions, and + // not just currently visible actions so it can make a decision on whether or + // not to force an expanded state. + container_->OnVisibleActionsChanged(GetTopVisibleActions( + enabled_actions_, ignored_actions, GetMaxNumActions(true))); } void MediaNotificationView::UpdateViewForExpandedState() { @@ -398,7 +427,9 @@ void MediaNotificationView::UpdateViewForExpandedState() { views::BoxLayout::Orientation::kVertical, gfx::Insets( kDefaultMarginSize, kDefaultMarginSize, kDefaultMarginSize, - has_artwork_ ? kRightMarginExpandedSize : kDefaultMarginSize), + has_artwork_ + ? (notification_width_ * kMediaImageMaxWidthExpandedPct) + : kDefaultMarginSize), kDefaultMarginSize)) ->SetDefaultFlex(1); } else { @@ -409,7 +440,9 @@ void MediaNotificationView::UpdateViewForExpandedState() { ->SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, gfx::Insets(0, kDefaultMarginSize, 14, - has_artwork_ ? kRightMarginSize : kDefaultMarginSize), + has_artwork_ + ? (notification_width_ * kMediaImageMaxWidthPct) + : kDefaultMarginSize), kDefaultMarginSize, true)) ->SetFlexForView(title_artist_row_, 1); } @@ -422,10 +455,9 @@ void MediaNotificationView::UpdateViewForExpandedState() { } header_row_->SetExpanded(expanded); + container_->OnExpanded(expanded); UpdateActionButtonsVisibility(); - - container_->OnExpanded(expanded); } void MediaNotificationView::CreateMediaButton( @@ -479,11 +511,11 @@ void MediaNotificationView::UpdateForegroundColor() { header_row_->SetBackgroundColor(background); // Update play/pause button images. - views::SetImageFromVectorIcon( + views::SetImageFromVectorIconWithColor( play_pause_button_, *GetVectorIconForMediaAction(MediaSessionAction::kPlay), kMediaButtonIconSize, foreground); - views::SetToggledImageFromVectorIcon( + views::SetToggledImageFromVectorIconWithColor( play_pause_button_, *GetVectorIconForMediaAction(MediaSessionAction::kPause), kMediaButtonIconSize, foreground); @@ -500,12 +532,14 @@ void MediaNotificationView::UpdateForegroundColor() { views::ImageButton* button = static_cast<views::ImageButton*>(child); - views::SetImageFromVectorIcon( + views::SetImageFromVectorIconWithColor( button, *GetVectorIconForMediaAction(GetActionFromButtonTag(*button)), kMediaButtonIconSize, foreground); button->SchedulePaint(); } + + container_->OnColorsChanged(foreground, background); } } // namespace media_message_center diff --git a/chromium/components/media_message_center/media_notification_view.h b/chromium/components/media_message_center/media_notification_view.h index 02263b99f14..e73c0e6de04 100644 --- a/chromium/components/media_message_center/media_notification_view.h +++ b/chromium/components/media_message_center/media_notification_view.h @@ -65,7 +65,9 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationView MediaNotificationView(MediaNotificationContainer* container, base::WeakPtr<MediaNotificationItem> item, views::View* header_row_controls_view, - const base::string16& default_app_name); + const base::string16& default_app_name, + int notification_width, + bool should_show_icon); ~MediaNotificationView() override; void SetExpanded(bool expanded); @@ -90,6 +92,12 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationView const std::set<media_session::mojom::MediaSessionAction>& actions); void UpdateWithMediaArtwork(const gfx::ImageSkia& image); + const views::Label* title_label_for_testing() const { return title_label_; } + + const views::Label* artist_label_for_testing() const { return artist_label_; } + + views::Button* GetHeaderRowForTesting() const; + private: friend class MediaNotificationViewTest; @@ -123,6 +131,9 @@ class COMPONENT_EXPORT(MEDIA_MESSAGE_CENTER) MediaNotificationView // String to set as the app name of the header when there is no source title. base::string16 default_app_name_; + // Width of the notification in pixels. Used for calculating artwork bounds. + int notification_width_; + bool has_artwork_ = false; // Whether this notification is expanded or not. diff --git a/chromium/components/media_message_center/media_notification_view_unittest.cc b/chromium/components/media_message_center/media_notification_view_unittest.cc index 78921db25ba..f9d757099f7 100644 --- a/chromium/components/media_message_center/media_notification_view_unittest.cc +++ b/chromium/components/media_message_center/media_notification_view_unittest.cc @@ -10,7 +10,9 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/task_environment.h" #include "base/unguessable_token.h" +#include "build/build_config.h" #include "components/media_message_center/media_notification_background.h" #include "components/media_message_center/media_notification_constants.h" #include "components/media_message_center/media_notification_container.h" @@ -20,6 +22,7 @@ #include "services/media_session/public/mojom/audio_focus.mojom.h" #include "services/media_session/public/mojom/media_session.mojom.h" #include "testing/gmock/include/gmock/gmock.h" +#include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h" #include "ui/events/base_event_utils.h" #include "ui/message_center/message_center.h" @@ -51,7 +54,10 @@ const char kTestDefaultAppName[] = "default app name"; const char kTestAppName[] = "app name"; const gfx::Size kWidgetSize(500, 500); -const gfx::Size kViewSize(400, 400); + +constexpr int kViewWidth = 400; +constexpr int kViewArtworkWidth = kViewWidth * 0.4; +const gfx::Size kViewSize(kViewWidth, 400); // Checks if the view class name is used by a media button. bool IsMediaButtonType(const char* class_name) { @@ -84,9 +90,15 @@ class MockMediaNotificationContainer : public MediaNotificationContainer { // MediaNotificationContainer implementation. MOCK_METHOD1(OnExpanded, void(bool expanded)); + MOCK_METHOD1( + OnMediaSessionInfoChanged, + void(const media_session::mojom::MediaSessionInfoPtr& session_info)); + MOCK_METHOD0(OnMediaSessionMetadataChanged, void()); MOCK_METHOD1(OnVisibleActionsChanged, void(const std::set<MediaSessionAction>& actions)); MOCK_METHOD1(OnMediaArtworkChanged, void(const gfx::ImageSkia& image)); + MOCK_METHOD2(OnColorsChanged, void(SkColor foreground, SkColor background)); + MOCK_METHOD0(OnHeaderClicked, void()); MediaNotificationView* view() const { return view_.get(); } void SetView(std::unique_ptr<MediaNotificationView> view) { @@ -103,7 +115,9 @@ class MockMediaNotificationContainer : public MediaNotificationContainer { class MediaNotificationViewTest : public views::ViewsTestBase { public: - MediaNotificationViewTest() = default; + MediaNotificationViewTest() + : views::ViewsTestBase( + base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} ~MediaNotificationViewTest() override = default; void SetUp() override { @@ -191,8 +205,13 @@ class MediaNotificationViewTest : public views::ViewsTestBase { return media_controller_.get(); } + message_center::NotificationHeaderView* GetHeaderRow( + MediaNotificationView* view) const { + return view->header_row_; + } + message_center::NotificationHeaderView* header_row() const { - return view()->header_row_; + return GetHeaderRow(view()); } const base::string16& accessible_name() const { @@ -276,6 +295,12 @@ class MediaNotificationViewTest : public views::ViewsTestBase { static_cast<base::HistogramBase::Sample>(metadata), count); } + void AdvanceClockMilliseconds(int milliseconds) { + ASSERT_TRUE(task_environment_.has_value()); + task_environment_->FastForwardBy( + base::TimeDelta::FromMilliseconds(milliseconds)); + } + private: void NotifyUpdatedActions() { item_->MediaSessionActionsChanged( @@ -287,7 +312,8 @@ class MediaNotificationViewTest : public views::ViewsTestBase { auto view = std::make_unique<MediaNotificationView>( &container_, item_->GetWeakPtr(), nullptr /* header_row_controls_view */, - base::ASCIIToUTF16(kTestDefaultAppName)); + base::ASCIIToUTF16(kTestDefaultAppName), kViewWidth, + /*should_show_icon=*/true); view->SetSize(kViewSize); view->set_owned_by_client(); @@ -313,7 +339,15 @@ class MediaNotificationViewTest : public views::ViewsTestBase { DISALLOW_COPY_AND_ASSIGN(MediaNotificationViewTest); }; -TEST_F(MediaNotificationViewTest, ButtonsSanityCheck) { +// TODO(crbug.com/1009287): many of these tests are failing on TSan builds. +#if defined(THREAD_SANITIZER) +#define MAYBE_MediaNotificationViewTest DISABLED_MediaNotificationViewTest +class DISABLED_MediaNotificationViewTest : public MediaNotificationViewTest {}; +#else +#define MAYBE_MediaNotificationViewTest MediaNotificationViewTest +#endif + +TEST_F(MAYBE_MediaNotificationViewTest, ButtonsSanityCheck) { view()->SetExpanded(true); EnableAllActions(); @@ -343,7 +377,12 @@ TEST_F(MediaNotificationViewTest, ButtonsSanityCheck) { EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause)); } -TEST_F(MediaNotificationViewTest, ButtonsFocusCheck) { +#if defined(OS_WIN) +#define MAYBE_ButtonsFocusCheck DISABLED_ButtonsFocusCheck +#else +#define MAYBE_ButtonsFocusCheck ButtonsFocusCheck +#endif +TEST_F(MAYBE_MediaNotificationViewTest, MAYBE_ButtonsFocusCheck) { // Expand and enable all actions to show all buttons. view()->SetExpanded(true); EnableAllActions(); @@ -374,10 +413,12 @@ TEST_F(MediaNotificationViewTest, ButtonsFocusCheck) { focus_manager->GetFocusedView()); } -TEST_F(MediaNotificationViewTest, PlayPauseButtonTooltipCheck) { +TEST_F(MAYBE_MediaNotificationViewTest, PlayPauseButtonTooltipCheck) { EnableAction(MediaSessionAction::kPlay); EnableAction(MediaSessionAction::kPause); + EXPECT_CALL(container(), OnMediaSessionInfoChanged(_)); + auto* button = GetButtonForAction(MediaSessionAction::kPlay); base::string16 tooltip = button->GetTooltipText(gfx::Point()); EXPECT_FALSE(tooltip.empty()); @@ -394,7 +435,7 @@ TEST_F(MediaNotificationViewTest, PlayPauseButtonTooltipCheck) { EXPECT_NE(tooltip, new_tooltip); } -TEST_F(MediaNotificationViewTest, NextTrackButtonClick) { +TEST_F(MAYBE_MediaNotificationViewTest, NextTrackButtonClick) { EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_)); EnableAction(MediaSessionAction::kNextTrack); @@ -407,7 +448,7 @@ TEST_F(MediaNotificationViewTest, NextTrackButtonClick) { ExpectHistogramActionRecorded(MediaSessionAction::kNextTrack); } -TEST_F(MediaNotificationViewTest, PlayButtonClick) { +TEST_F(MAYBE_MediaNotificationViewTest, PlayButtonClick) { EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_)); EnableAction(MediaSessionAction::kPlay); @@ -420,9 +461,10 @@ TEST_F(MediaNotificationViewTest, PlayButtonClick) { ExpectHistogramActionRecorded(MediaSessionAction::kPlay); } -TEST_F(MediaNotificationViewTest, PauseButtonClick) { +TEST_F(MAYBE_MediaNotificationViewTest, PauseButtonClick) { EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_)); EnableAction(MediaSessionAction::kPause); + EXPECT_CALL(container(), OnMediaSessionInfoChanged(_)); EXPECT_EQ(0, media_controller()->suspend_count()); @@ -440,7 +482,7 @@ TEST_F(MediaNotificationViewTest, PauseButtonClick) { ExpectHistogramActionRecorded(MediaSessionAction::kPause); } -TEST_F(MediaNotificationViewTest, PreviousTrackButtonClick) { +TEST_F(MAYBE_MediaNotificationViewTest, PreviousTrackButtonClick) { EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_)); EnableAction(MediaSessionAction::kPreviousTrack); @@ -453,7 +495,7 @@ TEST_F(MediaNotificationViewTest, PreviousTrackButtonClick) { ExpectHistogramActionRecorded(MediaSessionAction::kPreviousTrack); } -TEST_F(MediaNotificationViewTest, SeekBackwardButtonClick) { +TEST_F(MAYBE_MediaNotificationViewTest, SeekBackwardButtonClick) { EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_)); EnableAction(MediaSessionAction::kSeekBackward); @@ -466,7 +508,7 @@ TEST_F(MediaNotificationViewTest, SeekBackwardButtonClick) { ExpectHistogramActionRecorded(MediaSessionAction::kSeekBackward); } -TEST_F(MediaNotificationViewTest, SeekForwardButtonClick) { +TEST_F(MAYBE_MediaNotificationViewTest, SeekForwardButtonClick) { EXPECT_CALL(controller(), LogMediaSessionActionButtonPressed(_)); EnableAction(MediaSessionAction::kSeekForward); @@ -479,7 +521,7 @@ TEST_F(MediaNotificationViewTest, SeekForwardButtonClick) { ExpectHistogramActionRecorded(MediaSessionAction::kSeekForward); } -TEST_F(MediaNotificationViewTest, PlayToggle_FromObserver_Empty) { +TEST_F(MAYBE_MediaNotificationViewTest, PlayToggle_FromObserver_Empty) { EnableAction(MediaSessionAction::kPlay); { @@ -500,7 +542,7 @@ TEST_F(MediaNotificationViewTest, PlayToggle_FromObserver_Empty) { } } -TEST_F(MediaNotificationViewTest, PlayToggle_FromObserver_PlaybackState) { +TEST_F(MAYBE_MediaNotificationViewTest, PlayToggle_FromObserver_PlaybackState) { EnableAction(MediaSessionAction::kPlay); EnableAction(MediaSessionAction::kPause); @@ -537,7 +579,7 @@ TEST_F(MediaNotificationViewTest, PlayToggle_FromObserver_PlaybackState) { } } -TEST_F(MediaNotificationViewTest, MetadataIsDisplayed) { +TEST_F(MAYBE_MediaNotificationViewTest, MetadataIsDisplayed) { view()->SetExpanded(true); EnableAllActions(); @@ -552,7 +594,7 @@ TEST_F(MediaNotificationViewTest, MetadataIsDisplayed) { EXPECT_EQ(kMediaTitleArtistRowExpectedHeight, title_artist_row()->height()); } -TEST_F(MediaNotificationViewTest, UpdateMetadata_FromObserver) { +TEST_F(MAYBE_MediaNotificationViewTest, UpdateMetadata_FromObserver) { EnableAllActions(); ExpectHistogramMetadataRecorded(MediaNotificationView::Metadata::kTitle, 1); @@ -567,6 +609,7 @@ TEST_F(MediaNotificationViewTest, UpdateMetadata_FromObserver) { metadata.artist = base::ASCIIToUTF16("artist2"); metadata.album = base::ASCIIToUTF16("album"); + EXPECT_CALL(container(), OnMediaSessionMetadataChanged()); GetItem()->MediaSessionMetadataChanged(metadata); view()->SetExpanded(true); @@ -590,7 +633,7 @@ TEST_F(MediaNotificationViewTest, UpdateMetadata_FromObserver) { ExpectHistogramMetadataRecorded(MediaNotificationView::Metadata::kCount, 2); } -TEST_F(MediaNotificationViewTest, UpdateMetadata_AppName) { +TEST_F(MAYBE_MediaNotificationViewTest, UpdateMetadata_AppName) { EXPECT_EQ(base::ASCIIToUTF16(kTestDefaultAppName), header_row()->app_name_for_testing()); @@ -616,11 +659,13 @@ TEST_F(MediaNotificationViewTest, UpdateMetadata_AppName) { header_row()->app_name_for_testing()); } -TEST_F(MediaNotificationViewTest, Buttons_WhenCollapsed) { - EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>( - {MediaSessionAction::kPlay, - MediaSessionAction::kPreviousTrack, - MediaSessionAction::kNextTrack}))); +TEST_F(MAYBE_MediaNotificationViewTest, Buttons_WhenCollapsed) { + EXPECT_CALL( + container(), + OnVisibleActionsChanged(std::set<MediaSessionAction>( + {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, + MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward, + MediaSessionAction::kSeekForward}))); EnableAllActions(); view()->SetExpanded(false); testing::Mock::VerifyAndClearExpectations(&container()); @@ -633,18 +678,21 @@ TEST_F(MediaNotificationViewTest, Buttons_WhenCollapsed) { EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekBackward)); EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); - EXPECT_CALL(container(), - OnVisibleActionsChanged(std::set<MediaSessionAction>( - {MediaSessionAction::kPlay, MediaSessionAction::kSeekBackward, - MediaSessionAction::kNextTrack}))); + EXPECT_CALL( + container(), + OnVisibleActionsChanged(std::set<MediaSessionAction>( + {MediaSessionAction::kPlay, MediaSessionAction::kSeekBackward, + MediaSessionAction::kNextTrack, MediaSessionAction::kSeekForward}))); DisableAction(MediaSessionAction::kPreviousTrack); testing::Mock::VerifyAndClearExpectations(&container()); EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); - EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>( - {MediaSessionAction::kPlay, - MediaSessionAction::kPreviousTrack, - MediaSessionAction::kNextTrack}))); + EXPECT_CALL( + container(), + OnVisibleActionsChanged(std::set<MediaSessionAction>( + {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, + MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward, + MediaSessionAction::kSeekForward}))); EnableAction(MediaSessionAction::kPreviousTrack); testing::Mock::VerifyAndClearExpectations(&container()); EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); @@ -652,25 +700,30 @@ TEST_F(MediaNotificationViewTest, Buttons_WhenCollapsed) { EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>( {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, - MediaSessionAction::kNextTrack}))); + MediaSessionAction::kNextTrack, + MediaSessionAction::kSeekBackward}))); DisableAction(MediaSessionAction::kSeekForward); testing::Mock::VerifyAndClearExpectations(&container()); EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); - EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>( - {MediaSessionAction::kPlay, - MediaSessionAction::kPreviousTrack, - MediaSessionAction::kNextTrack}))); + EXPECT_CALL( + container(), + OnVisibleActionsChanged(std::set<MediaSessionAction>( + {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, + MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward, + MediaSessionAction::kSeekForward}))); EnableAction(MediaSessionAction::kSeekForward); testing::Mock::VerifyAndClearExpectations(&container()); EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); } -TEST_F(MediaNotificationViewTest, Buttons_WhenExpanded) { - EXPECT_CALL(container(), OnVisibleActionsChanged(std::set<MediaSessionAction>( - {MediaSessionAction::kPlay, - MediaSessionAction::kPreviousTrack, - MediaSessionAction::kNextTrack}))); +TEST_F(MAYBE_MediaNotificationViewTest, Buttons_WhenExpanded) { + EXPECT_CALL( + container(), + OnVisibleActionsChanged(std::set<MediaSessionAction>( + {MediaSessionAction::kPlay, MediaSessionAction::kPreviousTrack, + MediaSessionAction::kNextTrack, MediaSessionAction::kSeekBackward, + MediaSessionAction::kSeekForward}))); EnableAllActions(); testing::Mock::VerifyAndClearExpectations(&container()); @@ -692,7 +745,7 @@ TEST_F(MediaNotificationViewTest, Buttons_WhenExpanded) { EXPECT_TRUE(IsActionButtonVisible(MediaSessionAction::kSeekForward)); } -TEST_F(MediaNotificationViewTest, ClickHeader_ToggleExpand) { +TEST_F(MAYBE_MediaNotificationViewTest, ClickHeader_ToggleExpand) { view()->SetExpanded(true); EnableAllActions(); @@ -707,7 +760,7 @@ TEST_F(MediaNotificationViewTest, ClickHeader_ToggleExpand) { EXPECT_TRUE(IsActuallyExpanded()); } -TEST_F(MediaNotificationViewTest, ActionButtonsHiddenByDefault) { +TEST_F(MAYBE_MediaNotificationViewTest, ActionButtonsHiddenByDefault) { EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPlay)); EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kNextTrack)); EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kPreviousTrack)); @@ -715,7 +768,7 @@ TEST_F(MediaNotificationViewTest, ActionButtonsHiddenByDefault) { EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kSeekBackward)); } -TEST_F(MediaNotificationViewTest, ActionButtonsToggleVisibility) { +TEST_F(MAYBE_MediaNotificationViewTest, ActionButtonsToggleVisibility) { EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kNextTrack)); EnableAction(MediaSessionAction::kNextTrack); @@ -727,11 +780,12 @@ TEST_F(MediaNotificationViewTest, ActionButtonsToggleVisibility) { EXPECT_FALSE(IsActionButtonVisible(MediaSessionAction::kNextTrack)); } -TEST_F(MediaNotificationViewTest, UpdateArtworkFromItem) { +TEST_F(MAYBE_MediaNotificationViewTest, UpdateArtworkFromItem) { int title_artist_width = title_artist_row()->width(); const SkColor accent = header_row()->accent_color_for_testing(); gfx::Size size = view()->size(); EXPECT_CALL(container(), OnMediaArtworkChanged(_)).Times(2); + EXPECT_CALL(container(), OnColorsChanged(_, _)).Times(2); SkBitmap image; image.allocN32Pixels(10, 10); @@ -748,6 +802,9 @@ TEST_F(MediaNotificationViewTest, UpdateArtworkFromItem) { // have artwork. EXPECT_GT(title_artist_width, title_artist_row()->width()); + // Ensure that the title artist row does not extend into the artwork bounds. + EXPECT_LE(kViewWidth - kViewArtworkWidth, title_artist_row()->width()); + // Ensure that the image is displayed in the background artwork and that the // size of the notification was not affected. EXPECT_FALSE(GetArtworkImage().isNull()); @@ -771,12 +828,12 @@ TEST_F(MediaNotificationViewTest, UpdateArtworkFromItem) { EXPECT_EQ(accent, header_row()->accent_color_for_testing()); } -TEST_F(MediaNotificationViewTest, ExpandableDefaultState) { +TEST_F(MAYBE_MediaNotificationViewTest, ExpandableDefaultState) { EXPECT_FALSE(IsActuallyExpanded()); EXPECT_FALSE(expand_button_enabled()); } -TEST_F(MediaNotificationViewTest, ExpandablePlayPauseActionCountsOnce) { +TEST_F(MAYBE_MediaNotificationViewTest, ExpandablePlayPauseActionCountsOnce) { view()->SetExpanded(true); EXPECT_FALSE(IsActuallyExpanded()); @@ -805,7 +862,7 @@ TEST_F(MediaNotificationViewTest, ExpandablePlayPauseActionCountsOnce) { EXPECT_TRUE(expand_button_enabled()); } -TEST_F(MediaNotificationViewTest, BecomeExpandableAndWasNotExpandable) { +TEST_F(MAYBE_MediaNotificationViewTest, BecomeExpandableAndWasNotExpandable) { view()->SetExpanded(true); EXPECT_FALSE(IsActuallyExpanded()); @@ -817,7 +874,8 @@ TEST_F(MediaNotificationViewTest, BecomeExpandableAndWasNotExpandable) { EXPECT_TRUE(expand_button_enabled()); } -TEST_F(MediaNotificationViewTest, BecomeExpandableButWasAlreadyExpandable) { +TEST_F(MAYBE_MediaNotificationViewTest, + BecomeExpandableButWasAlreadyExpandable) { view()->SetExpanded(true); EXPECT_FALSE(IsActuallyExpanded()); @@ -834,7 +892,7 @@ TEST_F(MediaNotificationViewTest, BecomeExpandableButWasAlreadyExpandable) { EXPECT_TRUE(expand_button_enabled()); } -TEST_F(MediaNotificationViewTest, BecomeNotExpandableAndWasExpandable) { +TEST_F(MAYBE_MediaNotificationViewTest, BecomeNotExpandableAndWasExpandable) { view()->SetExpanded(true); EXPECT_FALSE(IsActuallyExpanded()); @@ -854,7 +912,7 @@ TEST_F(MediaNotificationViewTest, BecomeNotExpandableAndWasExpandable) { EXPECT_FALSE(expand_button_enabled()); } -TEST_F(MediaNotificationViewTest, +TEST_F(MAYBE_MediaNotificationViewTest, BecomeNotExpandableButWasAlreadyNotExpandable) { view()->SetExpanded(true); @@ -867,7 +925,7 @@ TEST_F(MediaNotificationViewTest, EXPECT_FALSE(expand_button_enabled()); } -TEST_F(MediaNotificationViewTest, ActionButtonRowSizeAndAlignment) { +TEST_F(MAYBE_MediaNotificationViewTest, ActionButtonRowSizeAndAlignment) { EnableAction(MediaSessionAction::kPlay); views::Button* button = GetButtonForAction(MediaSessionAction::kPlay); @@ -887,7 +945,7 @@ TEST_F(MediaNotificationViewTest, ActionButtonRowSizeAndAlignment) { EXPECT_GT(button_x, button->GetBoundsInScreen().x()); } -TEST_F(MediaNotificationViewTest, NotifysContainerOfExpandedState) { +TEST_F(MAYBE_MediaNotificationViewTest, NotifysContainerOfExpandedState) { // Track the expanded state given to |container_|. bool expanded = false; EXPECT_CALL(container(), OnExpanded(_)) @@ -914,7 +972,7 @@ TEST_F(MediaNotificationViewTest, NotifysContainerOfExpandedState) { EXPECT_FALSE(expanded); } -TEST_F(MediaNotificationViewTest, AccessibleNodeData) { +TEST_F(MAYBE_MediaNotificationViewTest, AccessibleNodeData) { ui::AXNodeData data; view()->GetAccessibleNodeData(&data); @@ -923,12 +981,13 @@ TEST_F(MediaNotificationViewTest, AccessibleNodeData) { EXPECT_EQ(base::ASCIIToUTF16("title - artist"), accessible_name()); } -TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdateMetadata) { +TEST_F(MAYBE_MediaNotificationViewTest, Freezing_DoNotUpdateMetadata) { media_session::MediaMetadata metadata; metadata.title = base::ASCIIToUTF16("title2"); metadata.artist = base::ASCIIToUTF16("artist2"); metadata.album = base::ASCIIToUTF16("album"); + EXPECT_CALL(container(), OnMediaSessionMetadataChanged()).Times(0); GetItem()->Freeze(); GetItem()->MediaSessionMetadataChanged(metadata); @@ -936,11 +995,12 @@ TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdateMetadata) { EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText()); } -TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdateImage) { +TEST_F(MAYBE_MediaNotificationViewTest, Freezing_DoNotUpdateImage) { SkBitmap image; image.allocN32Pixels(10, 10); image.eraseColor(SK_ColorMAGENTA); EXPECT_CALL(container(), OnMediaArtworkChanged(_)).Times(0); + EXPECT_CALL(container(), OnColorsChanged(_, _)).Times(0); GetItem()->Freeze(); GetItem()->MediaControllerImageChanged( @@ -949,10 +1009,12 @@ TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdateImage) { EXPECT_TRUE(GetArtworkImage().isNull()); } -TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdatePlaybackState) { +TEST_F(MAYBE_MediaNotificationViewTest, Freezing_DoNotUpdatePlaybackState) { EnableAction(MediaSessionAction::kPlay); EnableAction(MediaSessionAction::kPause); + EXPECT_CALL(container(), OnMediaSessionInfoChanged(_)).Times(0); + GetItem()->Freeze(); EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay)); @@ -968,7 +1030,7 @@ TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdatePlaybackState) { EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause)); } -TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdateActions) { +TEST_F(MAYBE_MediaNotificationViewTest, Freezing_DoNotUpdateActions) { EXPECT_FALSE( GetButtonForAction(MediaSessionAction::kSeekForward)->GetVisible()); @@ -979,7 +1041,7 @@ TEST_F(MediaNotificationViewTest, Freezing_DoNotUpdateActions) { GetButtonForAction(MediaSessionAction::kSeekForward)->GetVisible()); } -TEST_F(MediaNotificationViewTest, Freezing_DisableInteraction) { +TEST_F(MAYBE_MediaNotificationViewTest, Freezing_DisableInteraction) { EnableAllActions(); EXPECT_EQ(0, media_controller()->next_track_count()); @@ -992,7 +1054,7 @@ TEST_F(MediaNotificationViewTest, Freezing_DisableInteraction) { EXPECT_EQ(0, media_controller()->next_track_count()); } -TEST_F(MediaNotificationViewTest, UnfreezingDoesntMissUpdates) { +TEST_F(MAYBE_MediaNotificationViewTest, UnfreezingDoesntMissUpdates) { EnableAction(MediaSessionAction::kPlay); EnableAction(MediaSessionAction::kPause); @@ -1042,7 +1104,159 @@ TEST_F(MediaNotificationViewTest, UnfreezingDoesntMissUpdates) { EXPECT_EQ(base::ASCIIToUTF16("artist2"), artist_label()->GetText()); } -TEST_F(MediaNotificationViewTest, ForcedExpandedState) { +TEST_F(MAYBE_MediaNotificationViewTest, UnfreezingWaitsForArtwork_Timeout) { + EnableAction(MediaSessionAction::kPlay); + EnableAction(MediaSessionAction::kPause); + + // Set an image before freezing. + SkBitmap initial_image; + initial_image.allocN32Pixels(10, 10); + initial_image.eraseColor(SK_ColorMAGENTA); + GetItem()->MediaControllerImageChanged( + media_session::mojom::MediaSessionImageType::kArtwork, initial_image); + EXPECT_FALSE(GetArtworkImage().isNull()); + + // Freeze the item and clear the metadata. + GetItem()->Freeze(); + GetItem()->MediaSessionInfoChanged(nullptr); + GetItem()->MediaSessionMetadataChanged(base::nullopt); + GetItem()->MediaControllerImageChanged( + media_session::mojom::MediaSessionImageType::kArtwork, SkBitmap()); + + // The item should be frozen and the view should contain the old data. + EXPECT_TRUE(GetItem()->frozen()); + EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay)); + EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause)); + EXPECT_EQ(base::ASCIIToUTF16("title"), title_label()->GetText()); + EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText()); + EXPECT_FALSE(GetArtworkImage().isNull()); + + // Bind the item to a new controller that's playing instead of paused. + auto new_media_controller = std::make_unique<TestMediaController>(); + media_session::mojom::MediaSessionInfoPtr session_info( + media_session::mojom::MediaSessionInfo::New()); + session_info->playback_state = + media_session::mojom::MediaPlaybackState::kPlaying; + session_info->is_controllable = true; + GetItem()->SetController(new_media_controller->CreateMediaControllerRemote(), + session_info.Clone()); + + // The item will receive a MediaSessionInfoChanged. + GetItem()->MediaSessionInfoChanged(session_info.Clone()); + + // The item should still be frozen, and the view should contain the old data. + EXPECT_TRUE(GetItem()->frozen()); + EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay)); + EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause)); + EXPECT_EQ(base::ASCIIToUTF16("title"), title_label()->GetText()); + EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText()); + EXPECT_FALSE(GetArtworkImage().isNull()); + + // Update the metadata. + media_session::MediaMetadata metadata; + metadata.title = base::ASCIIToUTF16("title2"); + metadata.artist = base::ASCIIToUTF16("artist2"); + GetItem()->MediaSessionMetadataChanged(metadata); + + // The item should still be frozen, and waiting for a new image. + EXPECT_TRUE(GetItem()->frozen()); + EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay)); + EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause)); + EXPECT_EQ(base::ASCIIToUTF16("title"), title_label()->GetText()); + EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText()); + EXPECT_FALSE(GetArtworkImage().isNull()); + + // Once the freeze timer fires, the item should unfreeze even if there's no + // artwork. + AdvanceClockMilliseconds(2600); + + EXPECT_FALSE(GetItem()->frozen()); + EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPlay)); + EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPause)); + EXPECT_EQ(base::ASCIIToUTF16("title2"), title_label()->GetText()); + EXPECT_EQ(base::ASCIIToUTF16("artist2"), artist_label()->GetText()); + EXPECT_TRUE(GetArtworkImage().isNull()); +} + +TEST_F(MAYBE_MediaNotificationViewTest, + UnfreezingWaitsForArtwork_ReceiveArtwork) { + EnableAction(MediaSessionAction::kPlay); + EnableAction(MediaSessionAction::kPause); + + // Set an image before freezing. + SkBitmap initial_image; + initial_image.allocN32Pixels(10, 10); + initial_image.eraseColor(SK_ColorMAGENTA); + GetItem()->MediaControllerImageChanged( + media_session::mojom::MediaSessionImageType::kArtwork, initial_image); + EXPECT_FALSE(GetArtworkImage().isNull()); + + // Freeze the item and clear the metadata. + GetItem()->Freeze(); + GetItem()->MediaSessionInfoChanged(nullptr); + GetItem()->MediaSessionMetadataChanged(base::nullopt); + GetItem()->MediaControllerImageChanged( + media_session::mojom::MediaSessionImageType::kArtwork, SkBitmap()); + + // The item should be frozen and the view should contain the old data. + EXPECT_TRUE(GetItem()->frozen()); + EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay)); + EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause)); + EXPECT_EQ(base::ASCIIToUTF16("title"), title_label()->GetText()); + EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText()); + EXPECT_FALSE(GetArtworkImage().isNull()); + + // Bind the item to a new controller that's playing instead of paused. + auto new_media_controller = std::make_unique<TestMediaController>(); + media_session::mojom::MediaSessionInfoPtr session_info( + media_session::mojom::MediaSessionInfo::New()); + session_info->playback_state = + media_session::mojom::MediaPlaybackState::kPlaying; + session_info->is_controllable = true; + GetItem()->SetController(new_media_controller->CreateMediaControllerRemote(), + session_info.Clone()); + + // The item will receive a MediaSessionInfoChanged. + GetItem()->MediaSessionInfoChanged(session_info.Clone()); + + // The item should still be frozen, and the view should contain the old data. + EXPECT_TRUE(GetItem()->frozen()); + EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay)); + EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause)); + EXPECT_EQ(base::ASCIIToUTF16("title"), title_label()->GetText()); + EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText()); + EXPECT_FALSE(GetArtworkImage().isNull()); + + // Update the metadata. + media_session::MediaMetadata metadata; + metadata.title = base::ASCIIToUTF16("title2"); + metadata.artist = base::ASCIIToUTF16("artist2"); + GetItem()->MediaSessionMetadataChanged(metadata); + + // The item should still be frozen, and waiting for a new image. + EXPECT_TRUE(GetItem()->frozen()); + EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPlay)); + EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPause)); + EXPECT_EQ(base::ASCIIToUTF16("title"), title_label()->GetText()); + EXPECT_EQ(base::ASCIIToUTF16("artist"), artist_label()->GetText()); + EXPECT_FALSE(GetArtworkImage().isNull()); + + // Once we receive artwork, the item should unfreeze. + SkBitmap new_image; + new_image.allocN32Pixels(10, 10); + new_image.eraseColor(SK_ColorYELLOW); + GetItem()->MediaControllerImageChanged( + media_session::mojom::MediaSessionImageType::kArtwork, new_image); + + EXPECT_FALSE(GetItem()->frozen()); + EXPECT_FALSE(GetButtonForAction(MediaSessionAction::kPlay)); + EXPECT_TRUE(GetButtonForAction(MediaSessionAction::kPause)); + EXPECT_EQ(base::ASCIIToUTF16("title2"), title_label()->GetText()); + EXPECT_EQ(base::ASCIIToUTF16("artist2"), artist_label()->GetText()); + EXPECT_FALSE(GetArtworkImage().isNull()); +} + +TEST_F(MAYBE_MediaNotificationViewTest, ForcedExpandedState) { // Make the view expandable. EnableAllActions(); @@ -1075,4 +1289,23 @@ TEST_F(MediaNotificationViewTest, ForcedExpandedState) { EXPECT_TRUE(IsActuallyExpanded()); } +TEST_F(MAYBE_MediaNotificationViewTest, AllowsHidingOfAppIcon) { + MediaNotificationView shows_icon(&container(), nullptr, nullptr, + base::string16(), kViewWidth, + /*should_show_icon=*/true); + MediaNotificationView hides_icon(&container(), nullptr, nullptr, + base::string16(), kViewWidth, + /*should_show_icon=*/false); + + EXPECT_TRUE( + GetHeaderRow(&shows_icon)->app_icon_view_for_testing()->GetVisible()); + EXPECT_FALSE( + GetHeaderRow(&hides_icon)->app_icon_view_for_testing()->GetVisible()); +} + +TEST_F(MAYBE_MediaNotificationViewTest, ClickHeader_NotifyContainer) { + EXPECT_CALL(container(), OnHeaderClicked()); + SimulateHeaderClick(); +} + } // namespace media_message_center |