| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ash/eol_notification.h" |
| |
| #include <memory> |
| #include <string> |
| |
| #include "ash/constants/ash_features.h" |
| #include "ash/constants/ash_switches.h" |
| #include "ash/public/cpp/ash_view_ids.h" |
| #include "ash/public/cpp/system_tray_test_api.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/run_loop.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/simple_test_clock.h" |
| #include "chrome/browser/ash/login/session/user_session_manager.h" |
| #include "chrome/browser/ash/login/test/device_state_mixin.h" |
| #include "chrome/browser/ash/login/test/guest_session_mixin.h" |
| #include "chrome/browser/ash/login/test/logged_in_user_mixin.h" |
| #include "chrome/browser/ash/login/test/session_manager_state_waiter.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/notifications/notification_display_service_tester.h" |
| #include "chrome/browser/notifications/notification_test_util.h" |
| #include "chrome/browser/notifications/notification_ui_manager.h" |
| #include "chrome/browser/profiles/profile_manager.h" |
| #include "chrome/browser/profiles/profile_manager_observer.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_finder.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/test/base/mixin_based_in_process_browser_test.h" |
| #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h" |
| #include "chromeos/ash/components/dbus/update_engine/fake_update_engine_client.h" |
| #include "chromeos/ash/components/dbus/update_engine/update_engine_client.h" |
| #include "components/session_manager/core/session_manager.h" |
| #include "components/user_manager/user_manager.h" |
| #include "content/public/test/browser_test.h" |
| |
| namespace ash { |
| |
| namespace { |
| |
| constexpr char kEolNotificationId[] = "chrome://product_eol"; |
| |
| enum class TestCase { |
| kIncentivesDisabled, |
| kIncentivesWithoutOffer, |
| kIncentivesWithOffer, |
| kIncentivesWithOfferAndAUEWarning, |
| }; |
| |
| // Returns the "incentive_type" feature param to be used for a test case. |
| std::string GetTestFeatureParamString(TestCase test_case) { |
| switch (test_case) { |
| case TestCase::kIncentivesDisabled: |
| NOTREACHED_IN_MIGRATION(); |
| return ""; |
| case TestCase::kIncentivesWithoutOffer: |
| return "no_offer"; |
| case TestCase::kIncentivesWithOffer: |
| return "offer"; |
| case TestCase::kIncentivesWithOfferAndAUEWarning: |
| return "offer_with_warning"; |
| } |
| } |
| |
| // Sets up a test's scoped feature list to run enable the provided test case. |
| void SetUpScopedFeatureListForTestCase( |
| TestCase test_case, |
| base::test::ScopedFeatureList* scoped_feature_list) { |
| if (test_case == TestCase::kIncentivesDisabled) { |
| scoped_feature_list->InitAndDisableFeature(features::kEolIncentive); |
| } else { |
| scoped_feature_list->InitAndEnableFeatureWithParameters( |
| features::kEolIncentive, |
| {{"incentive_type", GetTestFeatureParamString(test_case)}}); |
| } |
| } |
| |
| // Possible results for `EolStatusMixin::SetUpTime()`. |
| enum class TimeSetupResult { |
| kSuccess, |
| kInvalidNow, |
| kInvalidEol, |
| kInvalidProfileCreation |
| }; |
| |
| // A mixin that injects a stub notification display service that tracks set of |
| // notifications for the primary profile. Expected to be used with test that go |
| // through login flow, and the primary user profile is different than the |
| // browser test profile (`browser()->profile()`). |
| class NotificationDisplayServiceMixin : public InProcessBrowserTestMixin, |
| public ProfileManagerObserver { |
| public: |
| explicit NotificationDisplayServiceMixin( |
| InProcessBrowserTestMixinHost* mixin_host) |
| : InProcessBrowserTestMixin(mixin_host) {} |
| |
| NotificationDisplayServiceMixin(const NotificationDisplayServiceMixin&) = |
| delete; |
| NotificationDisplayServiceMixin& operator=( |
| const NotificationDisplayServiceMixin&) = delete; |
| |
| ~NotificationDisplayServiceMixin() override = default; |
| |
| // InProcessBrowserTestMixin: |
| void SetUpOnMainThread() override { |
| // The mixin observes profile manager, and initializes the test notification |
| // service when the primary user profile gets added. If primary user (and |
| // profile) have already been created at this point, the mixin will not be |
| // able to detect profile addition. |
| ASSERT_FALSE(user_manager::UserManager::Get()->GetPrimaryUser()); |
| profile_waiter_ = std::make_unique<base::RunLoop>(); |
| profile_manager_observer_.Observe(g_browser_process->profile_manager()); |
| } |
| |
| void TearDownOnMainThread() override { |
| profile_manager_observer_.Reset(); |
| profile_waiter_.reset(); |
| display_service_.reset(); |
| } |
| |
| // ProfileManagerObserver: |
| void OnProfileAdded(Profile* profile) override { |
| if (!user_manager::UserManager::Get()->IsPrimaryUser( |
| BrowserContextHelper::Get()->GetUserByBrowserContext(profile))) { |
| return; |
| } |
| profile_manager_observer_.Reset(); |
| display_service_ = |
| std::make_unique<NotificationDisplayServiceTester>(profile); |
| profile_waiter_->Quit(); |
| } |
| |
| NotificationDisplayServiceTester* WaitForDisplayService() { |
| if (!display_service_ && !profile_manager_observer_.IsObserving()) { |
| return nullptr; |
| } |
| |
| profile_waiter_->Run(); |
| return display_service_.get(); |
| } |
| |
| private: |
| base::ScopedObservation<ProfileManager, ProfileManagerObserver> |
| profile_manager_observer_{this}; |
| std::unique_ptr<NotificationDisplayServiceTester> display_service_; |
| std::unique_ptr<base::RunLoop> profile_waiter_; |
| }; |
| |
| // Mixin that sets up session state to indicate certain EOL status: |
| // It can override EOL date provided returned by update engine, the current time |
| // used by EOL notification handler, and profile creation time. |
| class EolStatusMixin : public InProcessBrowserTestMixin { |
| public: |
| explicit EolStatusMixin(InProcessBrowserTestMixinHost* mixin_host) |
| : InProcessBrowserTestMixin(mixin_host) {} |
| |
| EolStatusMixin(const EolStatusMixin&) = delete; |
| EolStatusMixin& operator=(const EolStatusMixin&) = delete; |
| |
| ~EolStatusMixin() override = default; |
| |
| // InProcessBrowserTestMixin: |
| void SetUpInProcessBrowserTestFixture() override { |
| InProcessBrowserTestMixin::SetUpInProcessBrowserTestFixture(); |
| update_engine_client_ = UpdateEngineClient::InitializeFakeForTest(); |
| } |
| |
| void SetUpOnMainThread() override { |
| InProcessBrowserTestMixin::SetUpOnMainThread(); |
| UserSessionManager::GetInstance() |
| ->SetEolNotificationHandlerFactoryForTesting( |
| base::BindRepeating(&EolStatusMixin::CreateEolNotificationHandler, |
| base::Unretained(this))); |
| } |
| void TearDownOnMainThread() override { |
| UserSessionManager::GetInstance() |
| ->SetEolNotificationHandlerFactoryForTesting( |
| UserSessionManager::EolNotificationHandlerFactoryCallback()); |
| |
| InProcessBrowserTestMixin::TearDownOnMainThread(); |
| } |
| |
| // Sets up times relevant to calculating EOL notification status. |
| // `now_string` - The time used by EOL notification handler. |
| // `eol_string` - The time reportted by fake update engine as device EOL. |
| // `profile_creation_string` - The time used to override user profile creation |
| // when EOL notification handler gets created. |
| // Callers should verify that the method returned kSuccess. |
| [[nodiscard]] TimeSetupResult SetUpTime(const char* now_string, |
| const char* eol_string, |
| const char* profile_creation_string) { |
| base::Time now; |
| if (!base::Time::FromUTCString(now_string, &now)) { |
| return TimeSetupResult::kInvalidNow; |
| } |
| |
| base::Time eol; |
| if (!base::Time::FromUTCString(eol_string, &eol)) { |
| return TimeSetupResult::kInvalidEol; |
| } |
| |
| if (!base::Time::FromUTCString(profile_creation_string, |
| &profile_creation_time_)) { |
| return TimeSetupResult::kInvalidProfileCreation; |
| } |
| |
| clock_.SetNow(now); |
| update_engine_client_->set_eol_date(eol); |
| return TimeSetupResult::kSuccess; |
| } |
| |
| private: |
| std::unique_ptr<EolNotification> CreateEolNotificationHandler( |
| Profile* profile) { |
| auto eol_notification = std::make_unique<EolNotification>(profile); |
| eol_notification->OverrideClockForTesting(&clock_); |
| if (!profile_creation_time_.is_null()) { |
| profile->SetCreationTimeForTesting(profile_creation_time_); |
| } |
| return eol_notification; |
| } |
| |
| raw_ptr<FakeUpdateEngineClient, DanglingUntriaged> update_engine_client_ = |
| nullptr; |
| base::SimpleTestClock clock_; |
| base::Time profile_creation_time_; |
| }; |
| |
| } // namespace |
| |
| // Tests that verify EOL notifications for regular users on non-managed devices. |
| class EolNotificationTest : public MixinBasedInProcessBrowserTest, |
| public ::testing::WithParamInterface<TestCase> { |
| public: |
| EolNotificationTest() { |
| SetUpScopedFeatureListForTestCase(GetParam(), &scoped_feature_list_); |
| } |
| |
| bool NotificationHasClaimButton() { |
| return GetParam() != TestCase::kIncentivesDisabled; |
| } |
| |
| std::u16string GetEolApproachingNotificationTitle( |
| const std::u16string& eol_month) const { |
| switch (GetParam()) { |
| case TestCase::kIncentivesDisabled: |
| return u"Updates end " + eol_month; |
| case TestCase::kIncentivesWithoutOffer: |
| return u"Security updates end soon. Upgrade to a new Chromebook."; |
| case TestCase::kIncentivesWithOffer: |
| return u"Save $50 or more on a new Chromebook, when you upgrade today"; |
| case TestCase::kIncentivesWithOfferAndAUEWarning: |
| return u"Security updates end soon. Save $50 or more on a new " |
| u"Chromebook."; |
| } |
| } |
| |
| std::u16string GetEolApproachingNotificationMessage( |
| const std::string& eol_month) const { |
| switch (GetParam()) { |
| case TestCase::kIncentivesDisabled: |
| return u"You'll still be able to use this Chrome device after that " |
| u"time, but it will no longer get automatic software and " |
| u"security updates"; |
| case TestCase::kIncentivesWithoutOffer: |
| return base::UTF8ToUTF16(base::StringPrintf( |
| "You will stop getting security and software updates for this " |
| "Chromebook in %s. Upgrade your Chromebook for the best " |
| "experience.", |
| eol_month.c_str())); |
| case TestCase::kIncentivesWithOffer: |
| case TestCase::kIncentivesWithOfferAndAUEWarning: |
| return base::UTF8ToUTF16( |
| base::StringPrintf("You will stop getting security updates for " |
| "this Chromebook in %s. Time to upgrade for " |
| "the latest security and software. Offer " |
| "terms apply.", |
| eol_month.c_str())); |
| } |
| } |
| |
| std::u16string GetRecentEolNotificationTitle() const { |
| switch (GetParam()) { |
| case TestCase::kIncentivesDisabled: |
| return u"Final software update"; |
| case TestCase::kIncentivesWithoutOffer: |
| return u"Security updates have ended. Upgrade to a new Chromebook."; |
| case TestCase::kIncentivesWithOffer: |
| return u"Save $50 or more on a new Chromebook, when you upgrade today"; |
| case TestCase::kIncentivesWithOfferAndAUEWarning: |
| return u"Security updates have ended. Save $50 or more on a new " |
| u"Chromebook."; |
| } |
| } |
| |
| std::u16string GetRecentEolNotificationMessage() const { |
| switch (GetParam()) { |
| case TestCase::kIncentivesDisabled: |
| return u"This is the last automatic software and security update for " |
| u"this Chrome device. To get future updates, upgrade to a " |
| u"newer model."; |
| case TestCase::kIncentivesWithoutOffer: |
| return u"Your Chromebook is no longer receiving security and software " |
| u"updates. Upgrade your Chromebook for the best experience."; |
| case TestCase::kIncentivesWithOffer: |
| case TestCase::kIncentivesWithOfferAndAUEWarning: |
| return u"Your Chromebook is no longer receiving security updates. " |
| u"Time to upgrade for the latest security and software. " |
| u"Offer terms apply."; |
| } |
| } |
| |
| bool ShowsNotificationWithOffer() const { |
| switch (GetParam()) { |
| case TestCase::kIncentivesDisabled: |
| case TestCase::kIncentivesWithoutOffer: |
| return false; |
| case TestCase::kIncentivesWithOffer: |
| case TestCase::kIncentivesWithOfferAndAUEWarning: |
| return true; |
| } |
| } |
| |
| protected: |
| EolStatusMixin eol_status_mixin_{&mixin_host_}; |
| |
| NotificationDisplayServiceMixin notifications_mixin_{&mixin_host_}; |
| |
| ash::LoggedInUserMixin logged_in_user_mixin_{ |
| &mixin_host_, /*test_base=*/this, embedded_test_server(), |
| LoggedInUserMixin::LogInType::kConsumer}; |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| EolNotificationTest, |
| ::testing::Values(TestCase::kIncentivesDisabled, |
| TestCase::kIncentivesWithoutOffer, |
| TestCase::kIncentivesWithOffer, |
| TestCase::kIncentivesWithOfferAndAUEWarning)); |
| |
| // Tests that verify EOL notifications are not shown on managed devices. |
| class ManagedDeviceEolNotificationTest |
| : public MixinBasedInProcessBrowserTest, |
| public ::testing::WithParamInterface<TestCase> { |
| public: |
| ManagedDeviceEolNotificationTest() { |
| SetUpScopedFeatureListForTestCase(GetParam(), &scoped_feature_list_); |
| } |
| |
| protected: |
| EolStatusMixin eol_status_mixin_{&mixin_host_}; |
| |
| NotificationDisplayServiceMixin notifications_mixin_{&mixin_host_}; |
| |
| ash::DeviceStateMixin device_state_{ |
| &mixin_host_, |
| ash::DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED}; |
| |
| ash::LoggedInUserMixin logged_in_user_mixin_{ |
| &mixin_host_, /*test_base=*/this, embedded_test_server(), |
| LoggedInUserMixin::LogInType::kManaged}; |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| ManagedDeviceEolNotificationTest, |
| ::testing::Values(TestCase::kIncentivesDisabled, |
| TestCase::kIncentivesWithoutOffer, |
| TestCase::kIncentivesWithOffer, |
| TestCase::kIncentivesWithOfferAndAUEWarning)); |
| |
| // Tests that verify EOL notifications with incentives are not shown for child |
| // users. |
| class ChildUserEolNotificationTest |
| : public MixinBasedInProcessBrowserTest, |
| public ::testing::WithParamInterface<TestCase> { |
| public: |
| ChildUserEolNotificationTest() { |
| SetUpScopedFeatureListForTestCase(GetParam(), &scoped_feature_list_); |
| } |
| |
| protected: |
| EolStatusMixin eol_status_mixin_{&mixin_host_}; |
| |
| NotificationDisplayServiceMixin notifications_mixin_{&mixin_host_}; |
| |
| ash::LoggedInUserMixin logged_in_user_mixin_{ |
| &mixin_host_, /*test_base=*/this, embedded_test_server(), |
| LoggedInUserMixin::LogInType::kChild}; |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| ChildUserEolNotificationTest, |
| ::testing::Values(TestCase::kIncentivesDisabled, |
| TestCase::kIncentivesWithoutOffer, |
| TestCase::kIncentivesWithOffer, |
| TestCase::kIncentivesWithOfferAndAUEWarning)); |
| |
| class SuppressedNotificationTest : public MixinBasedInProcessBrowserTest, |
| public ::testing::WithParamInterface<bool> { |
| public: |
| SuppressedNotificationTest() { |
| scoped_feature_list_.InitWithFeatureState( |
| features::kSuppressFirstEolWarning, SuppressFirstWarningEnabled()); |
| } |
| |
| bool SuppressFirstWarningEnabled() { return GetParam(); } |
| |
| protected: |
| EolStatusMixin eol_status_mixin_{&mixin_host_}; |
| NotificationDisplayServiceMixin notifications_mixin_{&mixin_host_}; |
| ash::LoggedInUserMixin logged_in_user_mixin_{ |
| &mixin_host_, /*test_base=*/this, embedded_test_server(), |
| LoggedInUserMixin::LogInType::kConsumer}; |
| |
| private: |
| base::test::ScopedFeatureList scoped_feature_list_; |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P(All, SuppressedNotificationTest, testing::Bool()); |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, ShowNotificationForEolApproaching) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"12 May 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| ASSERT_TRUE(notification); |
| |
| EXPECT_EQ(GetEolApproachingNotificationTitle(u"June 2023"), |
| notification->title()); |
| EXPECT_EQ(GetEolApproachingNotificationMessage("June 2023"), |
| notification->message()); |
| |
| if (NotificationHasClaimButton()) { |
| notification_display_service->SimulateClick( |
| NotificationHandler::Type::TRANSIENT, notification->id(), |
| /*action_index=*/0, /*reply=*/std::nullopt); |
| content::WebContents* active_contents = |
| chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); |
| ASSERT_TRUE(active_contents); |
| EXPECT_EQ(ShowsNotificationWithOffer() |
| ? chrome::kEolIncentiveNotificationOfferURL |
| : chrome::kEolIncentiveNotificationNoOfferURL, |
| active_contents->GetVisibleURL()); |
| } |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, NoTrayNoticeWhenEolApproaches) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"12 May 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| logged_in_user_mixin_.LogInUser(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(SystemTrayTestApi().IsBubbleViewVisible( |
| VIEW_ID_QS_EOL_NOTICE_BUTTON, /*open_tray=*/true)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, |
| PRE_EolApproachingNotificationNotReshown) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"12 May 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| ASSERT_TRUE(notification); |
| notification_display_service->SimulateClick( |
| NotificationHandler::Type::TRANSIENT, notification->id(), |
| /*action_index=*/0, /*reply=*/std::nullopt); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, |
| EolApproachingNotificationNotReshown) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"12 May 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| EXPECT_FALSE(notification); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, |
| ShowEolApproachingNotificationForNewUsers) { |
| ASSERT_EQ( |
| TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime(/*now_string=*/"12 May 2023", |
| /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"01 April 2023")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| ASSERT_TRUE(notification); |
| |
| // Users that were created recently are not eligible for incentive |
| // notifications. |
| EXPECT_EQ(u"Updates end June 2023", notification->title()); |
| |
| notification_display_service->SimulateClick( |
| NotificationHandler::Type::TRANSIENT, notification->id(), |
| /*action_index=*/0, /*reply=*/std::nullopt); |
| content::WebContents* active_contents = |
| chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); |
| ASSERT_TRUE(active_contents); |
| EXPECT_EQ(GURL(chrome::kAutoUpdatePolicyURL), |
| active_contents->GetVisibleURL()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, ShowRecentEolNotification) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| ASSERT_TRUE(notification); |
| |
| EXPECT_EQ(GetRecentEolNotificationTitle(), notification->title()); |
| EXPECT_EQ(GetRecentEolNotificationMessage(), notification->message()); |
| |
| if (NotificationHasClaimButton()) { |
| notification_display_service->SimulateClick( |
| NotificationHandler::Type::TRANSIENT, notification->id(), |
| /*action_index=*/0, /*reply=*/std::nullopt); |
| content::WebContents* active_contents = |
| chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); |
| ASSERT_TRUE(active_contents); |
| EXPECT_EQ(ShowsNotificationWithOffer() |
| ? chrome::kEolIncentiveNotificationOfferURL |
| : chrome::kEolIncentiveNotificationNoOfferURL, |
| active_contents->GetVisibleURL()); |
| } |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, |
| PRE_RecentEolNotificationNotReshown) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| ASSERT_TRUE(notification); |
| |
| notification_display_service->SimulateClick( |
| NotificationHandler::Type::TRANSIENT, notification->id(), |
| /*action_index=*/0, /*reply=*/std::nullopt); |
| |
| // Verify quick settings notice still shows. |
| EXPECT_EQ( |
| GetParam() != TestCase::kIncentivesDisabled, |
| SystemTrayTestApi().IsBubbleViewVisible(VIEW_ID_QS_EOL_NOTICE_BUTTON, |
| /*open_tray=*/true)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, RecentEolNotificationNotReshown) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| EXPECT_EQ(GetParam() == TestCase::kIncentivesDisabled, !!notification); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, PRE_ShowTrayNoticeSoonAfterEol) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| logged_in_user_mixin_.LogInUser(); |
| base::RunLoop().RunUntilIdle(); |
| |
| const bool incentives_enabled = GetParam() != TestCase::kIncentivesDisabled; |
| SystemTrayTestApi tray_test_api; |
| ASSERT_EQ(incentives_enabled, |
| tray_test_api.IsBubbleViewVisible(VIEW_ID_QS_EOL_NOTICE_BUTTON, |
| /*open_tray=*/true)); |
| if (!incentives_enabled) { |
| return; |
| } |
| |
| tray_test_api.ClickBubbleView(VIEW_ID_QS_EOL_NOTICE_BUTTON); |
| |
| content::WebContents* active_contents = |
| chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); |
| ASSERT_TRUE(active_contents); |
| EXPECT_EQ(ShowsNotificationWithOffer() |
| ? chrome::kEolIncentiveNotificationOfferURL |
| : chrome::kEolIncentiveNotificationNoOfferURL, |
| active_contents->GetVisibleURL()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, ShowTrayNoticeSoonAfterEol) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| logged_in_user_mixin_.LogInUser(); |
| base::RunLoop().RunUntilIdle(); |
| |
| SystemTrayTestApi tray_test_api; |
| EXPECT_EQ(GetParam() != TestCase::kIncentivesDisabled, |
| tray_test_api.IsBubbleViewVisible(VIEW_ID_QS_EOL_NOTICE_BUTTON, |
| /*open_tray=*/true)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, NoTrayNoticeOnLockScreen) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| logged_in_user_mixin_.LogInUser(); |
| base::RunLoop().RunUntilIdle(); |
| |
| SessionManagerClient::Get()->RequestLockScreen(); |
| SessionStateWaiter(session_manager::SessionState::LOCKED).Wait(); |
| |
| SystemTrayTestApi tray_test_api; |
| EXPECT_FALSE(tray_test_api.IsBubbleViewVisible(VIEW_ID_QS_EOL_NOTICE_BUTTON, |
| /*open_tray=*/true)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, NoTrayNoticeBeforeLogin) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| base::RunLoop().RunUntilIdle(); |
| |
| SystemTrayTestApi tray_test_api; |
| EXPECT_FALSE(tray_test_api.IsBubbleViewVisible(VIEW_ID_QS_EOL_NOTICE_BUTTON, |
| /*open_tray=*/true)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, NoTrayNoticeForNewUsers) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 May 2023")); |
| logged_in_user_mixin_.LogInUser(); |
| base::RunLoop().RunUntilIdle(); |
| |
| SystemTrayTestApi tray_test_api; |
| EXPECT_FALSE(tray_test_api.IsBubbleViewVisible(VIEW_ID_QS_EOL_NOTICE_BUTTON, |
| /*open_tray=*/true)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, |
| ShowRecentEolNotificationForNewUsers) { |
| ASSERT_EQ( |
| TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime(/*now_string=*/"03 June 2023", |
| /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 May 2023")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| ASSERT_TRUE(notification); |
| |
| // Recently created users are not eligible for incentives notifications. |
| EXPECT_EQ(u"Final software update", notification->title()); |
| |
| notification_display_service->SimulateClick( |
| NotificationHandler::Type::TRANSIENT, notification->id(), |
| /*action_index=*/0, /*reply=*/std::nullopt); |
| content::WebContents* active_contents = |
| chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); |
| ASSERT_TRUE(active_contents); |
| EXPECT_EQ(GURL(chrome::kEolNotificationURL), |
| active_contents->GetVisibleURL()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, ShowNonRecentEolNotification) { |
| ASSERT_EQ( |
| TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime(/*now_string=*/"03 July 2023", |
| /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 May 2020")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| ASSERT_TRUE(notification); |
| |
| // Users should not see incentivized notification if they log in long after |
| // EOL. |
| EXPECT_EQ(u"Final software update", notification->title()); |
| |
| notification_display_service->SimulateClick( |
| NotificationHandler::Type::TRANSIENT, notification->id(), |
| /*action_index=*/0, /*reply=*/std::nullopt); |
| content::WebContents* active_contents = |
| chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); |
| ASSERT_TRUE(active_contents); |
| EXPECT_EQ(GURL(chrome::kEolNotificationURL), |
| active_contents->GetVisibleURL()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, PRE_ShowTrayNoticeLongAfterEol) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 August 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| logged_in_user_mixin_.LogInUser(); |
| base::RunLoop().RunUntilIdle(); |
| |
| const bool incentives_enabled = GetParam() != TestCase::kIncentivesDisabled; |
| SystemTrayTestApi tray_test_api; |
| ASSERT_EQ(incentives_enabled, |
| tray_test_api.IsBubbleViewVisible(VIEW_ID_QS_EOL_NOTICE_BUTTON, |
| /*open_tray=*/true)); |
| if (!incentives_enabled) { |
| return; |
| } |
| |
| tray_test_api.ClickBubbleView(VIEW_ID_QS_EOL_NOTICE_BUTTON); |
| |
| content::WebContents* active_contents = |
| chrome::FindLastActive()->tab_strip_model()->GetActiveWebContents(); |
| ASSERT_TRUE(active_contents); |
| EXPECT_EQ(chrome::kEolIncentiveNotificationNoOfferURL, |
| active_contents->GetVisibleURL()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(EolNotificationTest, ShowTrayNoticeLongAfterEol) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 August 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| logged_in_user_mixin_.LogInUser(); |
| base::RunLoop().RunUntilIdle(); |
| |
| SystemTrayTestApi tray_test_api; |
| EXPECT_EQ(GetParam() != TestCase::kIncentivesDisabled, |
| tray_test_api.IsBubbleViewVisible(VIEW_ID_QS_EOL_NOTICE_BUTTON, |
| /*open_tray=*/true)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(ManagedDeviceEolNotificationTest, |
| NoEolApproachingNotification) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"12 May 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| EXPECT_FALSE(notification); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(ManagedDeviceEolNotificationTest, |
| NoEolPassedNotification) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| EXPECT_FALSE(notification); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(ManagedDeviceEolNotificationTest, NoTrayNotice) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| logged_in_user_mixin_.LogInUser(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(SystemTrayTestApi().IsBubbleViewVisible( |
| VIEW_ID_QS_EOL_NOTICE_BUTTON, /*open_tray=*/true)); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(ChildUserEolNotificationTest, |
| NoEolApproachingNotification) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"12 May 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| ASSERT_TRUE(notification); |
| |
| EXPECT_EQ(u"Updates end June 2023", notification->title()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(ChildUserEolNotificationTest, NoEolPassedNotification) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| ASSERT_TRUE(notification); |
| |
| EXPECT_EQ(u"Final software update", notification->title()); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(ChildUserEolNotificationTest, NoTrayNotice) { |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"03 June 2023", /*eol_string=*/"01 June 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| logged_in_user_mixin_.LogInUser(); |
| base::RunLoop().RunUntilIdle(); |
| |
| EXPECT_FALSE(SystemTrayTestApi().IsBubbleViewVisible( |
| VIEW_ID_QS_EOL_NOTICE_BUTTON, /*open_tray=*/true)); |
| } |
| |
| // Test that the eol notification is not shown when just within 180 days, when |
| // first eol warning is suppressed. |
| IN_PROC_BROWSER_TEST_P(SuppressedNotificationTest, |
| EolNotificationSupressed180DaysBefore) { |
| // Set eol date to be 173 days in the future. |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"12 May 2023", /*eol_string=*/"1 November 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| EXPECT_EQ(SuppressFirstWarningEnabled(), !notification); |
| } |
| |
| // Test that the eol notification is shown when just within 90 days. |
| IN_PROC_BROWSER_TEST_P(SuppressedNotificationTest, |
| EolNotificationShown90DaysBefore) { |
| // Set eol date to be 83 days in the future. |
| ASSERT_EQ(TimeSetupResult::kSuccess, |
| eol_status_mixin_.SetUpTime( |
| /*now_string=*/"12 May 2023", /*eol_string=*/"3 August 2023", |
| /*profile_creation_string=*/"05 December 2021")); |
| |
| logged_in_user_mixin_.LogInUser(); |
| |
| NotificationDisplayServiceTester* notification_display_service = |
| notifications_mixin_.WaitForDisplayService(); |
| ASSERT_TRUE(notification_display_service); |
| |
| base::RunLoop().RunUntilIdle(); |
| |
| std::optional<message_center::Notification> notification = |
| notification_display_service->GetNotification(kEolNotificationId); |
| EXPECT_TRUE(notification); |
| } |
| |
| } // namespace ash |