| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ash/system/message_center/metrics_utils.h" |
| |
| #include <memory> |
| |
| #include "ash/constants/ash_features.h" |
| #include "ash/system/message_center/ash_message_popup_collection.h" |
| #include "ash/system/message_center/unified_message_center_bubble.h" |
| #include "ash/system/notification_center/notification_center_test_api.h" |
| #include "ash/system/notification_center/notification_center_view.h" |
| #include "ash/system/notification_center/notification_list_view.h" |
| #include "ash/system/unified/unified_system_tray.h" |
| #include "ash/test/ash_test_base.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/task_environment.h" |
| #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
| #include "ui/events/test/event_generator.h" |
| #include "ui/gfx/image/image.h" |
| #include "ui/message_center/message_center.h" |
| #include "ui/message_center/public/cpp/notification.h" |
| #include "ui/message_center/public/cpp/notifier_id.h" |
| #include "ui/views/widget/widget_utils.h" |
| |
| using message_center::Notification; |
| |
| namespace { |
| |
| constexpr char kNotificationViewTypeHistogramName[] = |
| "Ash.NotificationView.NotificationAdded.Type"; |
| |
| constexpr char kCountInOneGroupHistogramName[] = |
| "Ash.Notification.CountOfNotificationsInOneGroup"; |
| |
| constexpr char kGroupNotificationAddedHistogramName[] = |
| "Ash.Notification.GroupNotificationAdded"; |
| |
| constexpr char kSystemNotificationAddedHistogramName[] = |
| "Ash.NotifierFramework.SystemNotification.Added"; |
| |
| constexpr char kPinnedSystemNotificationAddedHistogramName[] = |
| "Ash.NotifierFramework.PinnedSystemNotification.Added"; |
| |
| constexpr char kSystemNotificationPopupShownHistogramName[] = |
| "Ash.NotifierFramework.SystemNotification.Popup.ShownCount"; |
| |
| constexpr char kSystemNotificationPopupUserJourneyTime[] = |
| "Ash.NotifierFramework.SystemNotification.Popup.UserJourneyTime"; |
| |
| constexpr char kSystemNotificationPopupDismissedWithin1s[] = |
| "Ash.NotifierFramework.SystemNotification.Popup.Dismissed.Within1s"; |
| |
| constexpr char kSystemNotificationPopupDismissedWithin7s[] = |
| "Ash.NotifierFramework.SystemNotification.Popup.Dismissed.Within7s"; |
| |
| constexpr char kSystemNotificationPopupDismissedAfter7s[] = |
| "Ash.NotifierFramework.SystemNotification.Popup.Dismissed.After7s"; |
| |
| const gfx::Image CreateTestImage() { |
| SkBitmap bitmap; |
| bitmap.allocN32Pixels(/*width=*/80, /*height=*/80); |
| bitmap.eraseColor(SK_ColorGREEN); |
| return gfx::Image::CreateFrom1xBitmap(bitmap); |
| } |
| |
| void CheckNotificationViewTypeRecorded( |
| std::unique_ptr<Notification> notification, |
| ash::metrics_utils::NotificationViewType type) { |
| base::HistogramTester histograms; |
| |
| // Add the notification. Expect that the corresponding notification type is |
| // recorded. |
| message_center::MessageCenter::Get()->AddNotification( |
| std::move(notification)); |
| histograms.ExpectBucketCount(kNotificationViewTypeHistogramName, type, 1); |
| } |
| |
| // A blocker that blocks a notification with the given ID. |
| class IdNotificationBlocker : public message_center::NotificationBlocker { |
| public: |
| explicit IdNotificationBlocker(message_center::MessageCenter* message_center) |
| : NotificationBlocker(message_center) {} |
| IdNotificationBlocker(const IdNotificationBlocker&) = delete; |
| IdNotificationBlocker& operator=(const IdNotificationBlocker&) = delete; |
| ~IdNotificationBlocker() override = default; |
| |
| void SetTargetIdAndNotifyBlock(const std::string& target_id) { |
| target_id_ = target_id; |
| NotifyBlockingStateChanged(); |
| } |
| |
| // message_center::NotificationBlocker: |
| bool ShouldShowNotification( |
| const message_center::Notification& notification) const override { |
| return notification.id() != target_id_; |
| } |
| |
| bool ShouldShowNotificationAsPopup( |
| const message_center::Notification& notification) const override { |
| return notification.id() != target_id_; |
| } |
| |
| private: |
| std::string target_id_; |
| }; |
| |
| // Returns true if a notification with a given `id` is showing a notification in |
| // the message center. |
| bool NotificationVisible(const std::string& id) { |
| return message_center::MessageCenter::Get()->FindVisibleNotificationById( |
| id) != nullptr; |
| } |
| |
| // Returns true if a notification with a given `id` has a pop-up. |
| bool PopupVisible(const std::string& id) { |
| return message_center::MessageCenter::Get()->FindPopupNotificationById(id) != |
| nullptr; |
| } |
| |
| } // namespace |
| |
| namespace ash { |
| |
| // This serves as an unit test class for all metrics recording in |
| // notification/message center. |
| class MessageCenterMetricsUtilsTest : public AshTestBase { |
| public: |
| MessageCenterMetricsUtilsTest() |
| : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} |
| MessageCenterMetricsUtilsTest(const MessageCenterMetricsUtilsTest&) = delete; |
| MessageCenterMetricsUtilsTest& operator=( |
| const MessageCenterMetricsUtilsTest&) = delete; |
| ~MessageCenterMetricsUtilsTest() override = default; |
| |
| // AshTestBase: |
| void SetUp() override { |
| AshTestBase::SetUp(); |
| test_delegate_ = |
| base::MakeRefCounted<message_center::NotificationDelegate>(); |
| notification_center_test_api_ = std::make_unique<NotificationCenterTestApi>( |
| /*tray=*/features::IsQsRevampEnabled() |
| ? GetPrimaryNotificationCenterTray() |
| : nullptr); |
| } |
| |
| // Create a test notification. Noted that the notifications are using the same |
| // url and profile id so that they are grouped together. |
| std::unique_ptr<Notification> CreateTestNotification() { |
| message_center::RichNotificationData data; |
| data.settings_button_handler = |
| message_center::SettingsButtonHandler::INLINE; |
| message_center::NotifierId notifier_id; |
| notifier_id.profile_id = "a@b.com"; |
| notifier_id.type = message_center::NotifierType::WEB_PAGE; |
| return std::make_unique<Notification>( |
| message_center::NOTIFICATION_TYPE_SIMPLE, |
| base::NumberToString(current_id_++), u"title", u"message", |
| ui::ImageModel(), u"display source", GURL(u"http://test-url.com"), |
| notifier_id, data, |
| /*delegate=*/nullptr); |
| } |
| |
| // Create a system notification with given `catalog_name`. |
| std::unique_ptr<Notification> CreateNotificationWithCatalogName( |
| NotificationCatalogName catalog_name) { |
| const std::string id = |
| "id" + base::NumberToString(static_cast<int>(catalog_name)); |
| message_center::RichNotificationData data; |
| return std::make_unique<Notification>( |
| message_center::NOTIFICATION_TYPE_SIMPLE, id, u"title", u"message", |
| ui::ImageModel(), u"display source", GURL(u"http://test-url.com"), |
| message_center::NotifierId( |
| message_center::NotifierType::SYSTEM_COMPONENT, id, catalog_name), |
| data, /*delegate=*/nullptr); |
| } |
| |
| // Create a pinned system notification with given `catalog_name`. |
| std::unique_ptr<Notification> CreatePinnedNotificationWithCatalogName( |
| NotificationCatalogName catalog_name) { |
| auto notification = CreateNotificationWithCatalogName(catalog_name); |
| notification->set_pinned(true); |
| return notification; |
| } |
| |
| // Get the notification view from message center associated with `id`. |
| views::View* GetNotificationViewFromMessageCenter(const std::string& id) { |
| return notification_center_test_api_->GetNotificationViewForId(id); |
| } |
| |
| // Get the popup notification view associated with `id`. |
| views::View* GetPopupNotificationView(const std::string& id) { |
| return notification_center_test_api_->GetPopupViewForId(id); |
| } |
| |
| void ClickView(views::View* view) { |
| ui::test::EventGenerator generator(GetRootWindow(view->GetWidget())); |
| gfx::Point cursor_location = view->GetBoundsInScreen().CenterPoint(); |
| generator.MoveMouseTo(cursor_location); |
| generator.ClickLeftButton(); |
| } |
| |
| void HoverOnView(views::View* view) { |
| ui::test::EventGenerator generator(GetRootWindow(view->GetWidget())); |
| gfx::Point cursor_location = view->GetBoundsInScreen().CenterPoint(); |
| generator.MoveMouseTo(cursor_location); |
| } |
| |
| scoped_refptr<message_center::NotificationDelegate> test_delegate() { |
| return test_delegate_; |
| } |
| |
| NotificationCenterTestApi* notification_center_test_api() { |
| return notification_center_test_api_.get(); |
| } |
| |
| private: |
| scoped_refptr<message_center::NotificationDelegate> test_delegate_; |
| std::unique_ptr<NotificationCenterTestApi> notification_center_test_api_; |
| |
| // Used to create test notification. This represents the current available |
| // number that we can use to create the next test notification. This id will |
| // be incremented whenever we create a new test notification. |
| int current_id_ = 0; |
| }; |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordBadClicks) { |
| base::HistogramTester histograms; |
| auto notification = CreateTestNotification(); |
| |
| // Add the notification and get its view in message center. |
| message_center::MessageCenter::Get()->AddNotification( |
| std::make_unique<message_center::Notification>(*notification)); |
| notification_center_test_api()->ToggleBubble(); |
| |
| // A click to a notification without a delegate should record a bad click. |
| ClickView(GetNotificationViewFromMessageCenter(notification->id())); |
| histograms.ExpectTotalCount("Notifications.Cros.Actions.ClickedBody.BadClick", |
| 1); |
| histograms.ExpectTotalCount( |
| "Notifications.Cros.Actions.ClickedBody.GoodClick", 0); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordGoodClicks) { |
| base::HistogramTester histograms; |
| auto notification = CreateTestNotification(); |
| notification->set_delegate(test_delegate()); |
| |
| // Add the notification and get its view in message center. |
| message_center::MessageCenter::Get()->AddNotification( |
| std::make_unique<message_center::Notification>(*notification)); |
| notification_center_test_api()->ToggleBubble(); |
| |
| // A click to a notification with a delegate should record a good click. |
| ClickView(GetNotificationViewFromMessageCenter(notification->id())); |
| histograms.ExpectTotalCount( |
| "Notifications.Cros.Actions.ClickedBody.GoodClick", 1); |
| histograms.ExpectTotalCount("Notifications.Cros.Actions.ClickedBody.BadClick", |
| 0); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordHover) { |
| // TODO(b/281705636): Fix metrics recording when QS revamp is enabled. |
| if (features::IsQsRevampEnabled()) { |
| return; |
| } |
| base::HistogramTester histograms; |
| auto notification = CreateTestNotification(); |
| |
| // Add the notification and get its view in message center. |
| message_center::MessageCenter::Get()->AddNotification( |
| std::make_unique<message_center::Notification>(*notification)); |
| |
| auto* popup = |
| notification_center_test_api()->GetPopupViewForId(notification->id()); |
| // Move the mouse hover on the popup notification view, expect hover action |
| // recorded. |
| HoverOnView(popup); |
| histograms.ExpectTotalCount("Notifications.Cros.Actions.Popup.Hover", 1); |
| |
| notification_center_test_api()->ToggleBubble(); |
| auto* notification_view = |
| GetNotificationViewFromMessageCenter(notification->id()); |
| |
| // Move the mouse hover on the notification view, expect hover action |
| // recorded. |
| HoverOnView(notification_view); |
| histograms.ExpectTotalCount("Notifications.Cros.Actions.Tray.Hover", 1); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordNotificationViewTypeSimple) { |
| message_center::MessageCenter::Get()->RemoveAllNotifications( |
| /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL); |
| |
| auto simple_notification = CreateTestNotification(); |
| CheckNotificationViewTypeRecorded( |
| std::move(simple_notification), |
| metrics_utils::NotificationViewType::SIMPLE); |
| |
| auto grouped_simple_notification = CreateTestNotification(); |
| CheckNotificationViewTypeRecorded( |
| std::move(grouped_simple_notification), |
| metrics_utils::NotificationViewType::GROUPED_SIMPLE); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordNotificationViewTypeImage) { |
| message_center::MessageCenter::Get()->RemoveAllNotifications( |
| /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL); |
| |
| auto image_notification = CreateTestNotification(); |
| image_notification->set_image(CreateTestImage()); |
| CheckNotificationViewTypeRecorded( |
| std::move(image_notification), |
| metrics_utils::NotificationViewType::HAS_IMAGE); |
| |
| auto grouped_image_notification = CreateTestNotification(); |
| grouped_image_notification->set_image(CreateTestImage()); |
| CheckNotificationViewTypeRecorded( |
| std::move(grouped_image_notification), |
| metrics_utils::NotificationViewType::GROUPED_HAS_IMAGE); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordNotificationViewTypeActionButtons) { |
| message_center::MessageCenter::Get()->RemoveAllNotifications( |
| /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL); |
| |
| auto notification = CreateTestNotification(); |
| notification->set_buttons({message_center::ButtonInfo(u"Test button")}); |
| CheckNotificationViewTypeRecorded( |
| std::move(notification), metrics_utils::NotificationViewType::HAS_ACTION); |
| |
| auto grouped_notification = CreateTestNotification(); |
| grouped_notification->set_buttons( |
| {message_center::ButtonInfo(u"Test button")}); |
| CheckNotificationViewTypeRecorded( |
| std::move(grouped_notification), |
| metrics_utils::NotificationViewType::GROUPED_HAS_ACTION); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordNotificationViewTypeInlineReply) { |
| message_center::MessageCenter::Get()->RemoveAllNotifications( |
| /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL); |
| |
| auto create_inline_reply_button = []() { |
| message_center::ButtonInfo button(u"Test button"); |
| button.placeholder = std::u16string(); |
| return button; |
| }; |
| auto notification = CreateTestNotification(); |
| notification->set_buttons({create_inline_reply_button()}); |
| |
| CheckNotificationViewTypeRecorded( |
| std::move(notification), |
| metrics_utils::NotificationViewType::HAS_INLINE_REPLY); |
| |
| auto grouped_notification = CreateTestNotification(); |
| grouped_notification->set_buttons({create_inline_reply_button()}); |
| CheckNotificationViewTypeRecorded( |
| std::move(grouped_notification), |
| metrics_utils::NotificationViewType::GROUPED_HAS_INLINE_REPLY); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, |
| RecordNotificationViewTypeImageActionButtons) { |
| message_center::MessageCenter::Get()->RemoveAllNotifications( |
| /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL); |
| |
| auto notification = CreateTestNotification(); |
| notification->set_image(CreateTestImage()); |
| notification->set_buttons({message_center::ButtonInfo(u"Test button")}); |
| CheckNotificationViewTypeRecorded( |
| std::move(notification), |
| metrics_utils::NotificationViewType::HAS_IMAGE_AND_ACTION); |
| |
| auto grouped_notification = CreateTestNotification(); |
| grouped_notification->set_image(CreateTestImage()); |
| grouped_notification->set_buttons( |
| {message_center::ButtonInfo(u"Test button")}); |
| CheckNotificationViewTypeRecorded( |
| std::move(grouped_notification), |
| metrics_utils::NotificationViewType::GROUPED_HAS_IMAGE_AND_ACTION); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, |
| RecordNotificationViewTypeImageInlineReply) { |
| message_center::MessageCenter::Get()->RemoveAllNotifications( |
| /*by_user=*/true, message_center::MessageCenter::RemoveType::ALL); |
| |
| auto create_inline_reply_button = []() { |
| message_center::ButtonInfo button(u"Test button"); |
| button.placeholder = std::u16string(); |
| return button; |
| }; |
| auto notification = CreateTestNotification(); |
| notification->set_image(CreateTestImage()); |
| notification->set_buttons({create_inline_reply_button()}); |
| |
| CheckNotificationViewTypeRecorded( |
| std::move(notification), |
| metrics_utils::NotificationViewType::HAS_IMAGE_AND_INLINE_REPLY); |
| |
| auto grouped_notification = CreateTestNotification(); |
| grouped_notification->set_image(CreateTestImage()); |
| grouped_notification->set_buttons({create_inline_reply_button()}); |
| CheckNotificationViewTypeRecorded( |
| std::move(grouped_notification), |
| metrics_utils::NotificationViewType::GROUPED_HAS_IMAGE_AND_INLINE_REPLY); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordCountOfNotificationsInOneGroup) { |
| base::HistogramTester histograms; |
| |
| auto notification1 = CreateTestNotification(); |
| std::string id1 = notification1->id(); |
| auto notification2 = CreateTestNotification(); |
| std::string id2 = notification2->id(); |
| auto notification3 = CreateTestNotification(); |
| |
| message_center::MessageCenter::Get()->AddNotification( |
| std::move(notification1)); |
| message_center::MessageCenter::Get()->AddNotification( |
| std::move(notification2)); |
| |
| histograms.ExpectBucketCount(kCountInOneGroupHistogramName, 2, 1); |
| |
| message_center::MessageCenter::Get()->AddNotification( |
| std::move(notification3)); |
| histograms.ExpectBucketCount(kCountInOneGroupHistogramName, 3, 1); |
| |
| message_center::MessageCenter::Get()->RemoveNotification(id1, |
| /*by_user=*/true); |
| histograms.ExpectBucketCount(kCountInOneGroupHistogramName, 2, 2); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordGroupNotificationAddedType) { |
| base::HistogramTester histograms; |
| |
| auto notification1 = CreateTestNotification(); |
| auto notification2 = CreateTestNotification(); |
| auto notification3 = CreateTestNotification(); |
| |
| message_center::MessageCenter::Get()->AddNotification( |
| std::move(notification1)); |
| message_center::MessageCenter::Get()->AddNotification( |
| std::move(notification2)); |
| |
| // There should be 1 group parent that contains 2 group child notifications. |
| histograms.ExpectBucketCount( |
| kGroupNotificationAddedHistogramName, |
| metrics_utils::GroupNotificationType::GROUP_PARENT, 1); |
| histograms.ExpectBucketCount( |
| kGroupNotificationAddedHistogramName, |
| metrics_utils::GroupNotificationType::GROUP_CHILD, 2); |
| |
| message_center::MessageCenter::Get()->AddNotification( |
| std::move(notification3)); |
| histograms.ExpectBucketCount( |
| kGroupNotificationAddedHistogramName, |
| metrics_utils::GroupNotificationType::GROUP_PARENT, 1); |
| histograms.ExpectBucketCount( |
| kGroupNotificationAddedHistogramName, |
| metrics_utils::GroupNotificationType::GROUP_CHILD, 3); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordSystemNotificationAdded) { |
| base::HistogramTester histograms; |
| |
| // Create a system notification with `kTestCatalogName` for its catalog name. |
| const NotificationCatalogName test_catalog_name = |
| NotificationCatalogName::kTestCatalogName; |
| auto test_notification = CreateNotificationWithCatalogName(test_catalog_name); |
| message_center::MessageCenter::Get()->AddNotification( |
| std::move(test_notification)); |
| |
| // Check metrics are not recorded for `kTestCatalogName`. |
| histograms.ExpectBucketCount(kSystemNotificationAddedHistogramName, |
| test_catalog_name, 0); |
| |
| // Create system notifications with a valid catalog name, one for a non-pinned |
| // notification and one for a pinned one (e.g. Full Restore and Caps Lock). |
| const NotificationCatalogName catalog_name = |
| NotificationCatalogName::kFullRestore; |
| const NotificationCatalogName pinned_catalog_name = |
| NotificationCatalogName::kCapsLock; |
| auto notification = CreateNotificationWithCatalogName(catalog_name); |
| auto pinned_notification = |
| CreatePinnedNotificationWithCatalogName(pinned_catalog_name); |
| |
| // Add notifications to message center. |
| auto* message_center = message_center::MessageCenter::Get(); |
| message_center->AddNotification( |
| std::make_unique<message_center::Notification>(*notification)); |
| message_center->AddNotification( |
| std::make_unique<message_center::Notification>(*pinned_notification)); |
| |
| // Expect metric to be recorded for valid catalog names. |
| histograms.ExpectBucketCount(kSystemNotificationAddedHistogramName, |
| catalog_name, 1); |
| histograms.ExpectBucketCount(kPinnedSystemNotificationAddedHistogramName, |
| pinned_catalog_name, 1); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, |
| RecordSystemNotificationAddedWithNotificationBlockers) { |
| base::HistogramTester histograms; |
| |
| // Create a system notification with a valid catalog name (e.g. Full Restore). |
| const NotificationCatalogName catalog_name = |
| NotificationCatalogName::kFullRestore; |
| auto notification = CreateNotificationWithCatalogName(catalog_name); |
| |
| // Add notification to message center. |
| auto* message_center = message_center::MessageCenter::Get(); |
| message_center->AddNotification( |
| std::make_unique<message_center::Notification>(*notification)); |
| |
| // Verify notification was shown. |
| EXPECT_TRUE(PopupVisible(notification->id())); |
| EXPECT_TRUE(NotificationVisible(notification->id())); |
| |
| // Expect `Added` and `PopupShown` metrics to be recorded. |
| histograms.ExpectBucketCount(kSystemNotificationAddedHistogramName, |
| catalog_name, 1); |
| histograms.ExpectBucketCount(kSystemNotificationPopupShownHistogramName, |
| catalog_name, 1); |
| |
| // Apply a notification blocker. |
| IdNotificationBlocker blocker(message_center); |
| blocker.SetTargetIdAndNotifyBlock(notification->id()); |
| |
| // Add more notification instances to the message center. |
| message_center->RemoveNotification(notification->id(), /*by_user=*/false); |
| message_center->AddNotification( |
| std::make_unique<message_center::Notification>(*notification)); |
| |
| // Verify notification wasn't shown with notification blockers. |
| EXPECT_FALSE(PopupVisible(notification->id())); |
| EXPECT_FALSE(NotificationVisible(notification->id())); |
| |
| // Verify the `Added` metric is recorded even with notification blockers. |
| histograms.ExpectBucketCount(kSystemNotificationAddedHistogramName, |
| catalog_name, 2); |
| |
| // Verify `Popup Shown` metric is not recorded with notification blockers. |
| histograms.ExpectBucketCount(kSystemNotificationPopupShownHistogramName, |
| catalog_name, 1); |
| } |
| |
| TEST_F(MessageCenterMetricsUtilsTest, RecordPopupUserJourneyTime) { |
| base::HistogramTester histograms; |
| |
| // Create a non-pinned system notification with a valid catalog name. |
| const NotificationCatalogName catalog_name = |
| NotificationCatalogName::kFullRestore; |
| auto notification = CreateNotificationWithCatalogName(catalog_name); |
| |
| // Add notification to message center. Use the normal duration for adding the |
| // notification so that the recorded popup duration is expected. |
| auto* message_center = message_center::MessageCenter::Get(); |
| absl::optional<ui::ScopedAnimationDurationScaleMode> mode( |
| ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION); |
| message_center->AddNotification( |
| std::make_unique<message_center::Notification>(*notification)); |
| |
| // Wait for notification popup to time out. |
| constexpr base::TimeDelta kPopupTimeOutDuration(base::Seconds(7)); |
| task_environment()->FastForwardBy(kPopupTimeOutDuration); |
| |
| // Expect user journey time metric to record the popup duration due to timeout |
| // (value is between 6 and 7 seconds). |
| auto buckets = |
| histograms.GetAllSamples(kSystemNotificationPopupUserJourneyTime); |
| EXPECT_TRUE(buckets[0].min >= 6000 && buckets[0].min <= 7000); |
| histograms.ExpectBucketCount(kSystemNotificationPopupDismissedWithin7s, |
| catalog_name, 1); |
| mode.reset(); |
| message_center->RemoveNotification(notification->id(), /*by_user=*/true); |
| |
| // Dismiss popup within 1s. |
| notification->set_timestamp(base::Time::Now()); |
| message_center->AddNotification( |
| std::make_unique<message_center::Notification>(*notification)); |
| message_center->RemoveNotification(notification->id(), /*by_user=*/true); |
| task_environment()->FastForwardBy(kPopupTimeOutDuration); |
| histograms.ExpectBucketCount(kSystemNotificationPopupDismissedWithin1s, |
| catalog_name, 1); |
| |
| // Dismiss "never timeout" popup after 7s. |
| notification->set_timestamp(base::Time::Now()); |
| notification->set_never_timeout(true); |
| message_center->AddNotification( |
| std::make_unique<message_center::Notification>(*notification)); |
| task_environment()->FastForwardBy(kPopupTimeOutDuration + base::Seconds(1)); |
| message_center->RemoveNotification(notification->id(), /*by_user=*/true); |
| task_environment()->FastForwardBy(kPopupTimeOutDuration); |
| histograms.ExpectBucketCount(kSystemNotificationPopupDismissedAfter7s, |
| catalog_name, 1); |
| } |
| |
| } // namespace ash |