| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller.h" |
| |
| #include <memory> |
| #include <utility> |
| |
| #include "base/callback_helpers.h" |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/numerics/safe_conversions.h" |
| #include "base/test/mock_callback.h" |
| #include "base/test/power_monitor_test.h" |
| #include "base/test/task_environment.h" |
| #include "base/time/clock.h" |
| #include "base/time/tick_clock.h" |
| #include "base/time/time.h" |
| #include "base/values.h" |
| #include "build/chromeos_buildflags.h" |
| #include "chrome/browser/upgrade_detector/upgrade_detector.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/scoped_testing_local_state.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| #include "ash/shell.h" |
| #include "ash/test/ash_test_helper.h" |
| #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" |
| #include "components/session_manager/core/session_manager.h" |
| #include "components/user_manager/scoped_user_manager.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "ui/display/manager/display_configurator.h" |
| #include "ui/display/manager/test/action_logger.h" |
| #include "ui/display/manager/test/test_native_display_delegate.h" |
| #else |
| #include "chrome/browser/ui/views/frame/browser_view.h" |
| #include "chrome/browser/ui/views/frame/test_with_browser_view.h" |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| using ::testing::_; |
| using ::testing::Eq; |
| using ::testing::ResultOf; |
| using ::testing::Return; |
| |
| namespace { |
| |
| // A delegate interface for handling the actions taken by the controller. |
| class ControllerDelegate { |
| public: |
| virtual ~ControllerDelegate() = default; |
| virtual void NotifyRelaunchRecommended() = 0; |
| virtual void NotifyRelaunchRequired() = 0; |
| virtual void Close() = 0; |
| virtual void SetDeadline(base::Time deadline) = 0; |
| virtual void OnRelaunchDeadlineExpired() = 0; |
| |
| protected: |
| ControllerDelegate() = default; |
| }; |
| |
| // A fake controller that asks a delegate to do work. |
| class FakeRelaunchNotificationController |
| : public RelaunchNotificationController { |
| public: |
| FakeRelaunchNotificationController(UpgradeDetector* upgrade_detector, |
| const base::Clock* clock, |
| const base::TickClock* tick_clock, |
| ControllerDelegate* delegate) |
| : RelaunchNotificationController(upgrade_detector, clock, tick_clock), |
| delegate_(delegate) {} |
| |
| using RelaunchNotificationController::kRelaunchGracePeriod; |
| |
| base::Time IncreaseRelaunchDeadlineOnShow() { |
| return RelaunchNotificationController::IncreaseRelaunchDeadlineOnShow(); |
| } |
| |
| private: |
| void DoNotifyRelaunchRecommended(bool /*past_deadline*/) override { |
| delegate_->NotifyRelaunchRecommended(); |
| } |
| |
| void DoNotifyRelaunchRequired( |
| base::Time deadline, |
| base::OnceCallback<base::Time()> on_visible) override { |
| delegate_->NotifyRelaunchRequired(); |
| } |
| |
| void Close() override { delegate_->Close(); } |
| |
| void SetDeadline(base::Time deadline) override { |
| delegate_->SetDeadline(deadline); |
| } |
| |
| void OnRelaunchDeadlineExpired() override { |
| delegate_->OnRelaunchDeadlineExpired(); |
| } |
| |
| ControllerDelegate* delegate_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FakeRelaunchNotificationController); |
| }; |
| |
| // A mock delegate for testing. |
| class MockControllerDelegate : public ControllerDelegate { |
| public: |
| MOCK_METHOD0(NotifyRelaunchRecommended, void()); |
| MOCK_METHOD0(NotifyRelaunchRequired, void()); |
| MOCK_METHOD0(Close, void()); |
| MOCK_METHOD1(SetDeadline, void(base::Time)); |
| MOCK_METHOD0(OnRelaunchDeadlineExpired, void()); |
| }; |
| |
| // A fake UpgradeDetector. |
| class FakeUpgradeDetector : public UpgradeDetector { |
| public: |
| explicit FakeUpgradeDetector(const base::Clock* clock, |
| const base::TickClock* tick_clock) |
| : UpgradeDetector(clock, tick_clock) { |
| set_upgrade_detected_time(this->clock()->Now()); |
| } |
| |
| base::TimeDelta GetHighAnnoyanceLevelDelta() { |
| return GetAnnoyanceLevelDeadline(UpgradeDetector::UPGRADE_ANNOYANCE_HIGH) - |
| GetAnnoyanceLevelDeadline( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| } |
| |
| // UpgradeDetector: |
| base::Time GetAnnoyanceLevelDeadline( |
| FakeUpgradeDetector::UpgradeNotificationAnnoyanceLevel level) override { |
| switch (level) { |
| case UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED: |
| return upgrade_detected_time() + (2 / 3 * high_threshold_); |
| case UpgradeDetector::UPGRADE_ANNOYANCE_HIGH: |
| return upgrade_detected_time() + high_threshold_; |
| case UpgradeDetector::UPGRADE_ANNOYANCE_GRACE: |
| case UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW: |
| case UpgradeDetector::UPGRADE_ANNOYANCE_LOW: |
| case UpgradeDetector::UPGRADE_ANNOYANCE_NONE: |
| case UpgradeDetector::UPGRADE_ANNOYANCE_CRITICAL: |
| return base::Time(); |
| } |
| } |
| |
| // Sets the annoyance level to |level| and broadcasts the change to all |
| // observers. |
| void BroadcastLevelChange(UpgradeNotificationAnnoyanceLevel level) { |
| set_upgrade_notification_stage(level); |
| NotifyUpgrade(); |
| } |
| |
| // Sets the high annoyance threshold to |high_threshold| and broadcasts the |
| // change to all observers. |
| void BroadcastHighThresholdChange(base::TimeDelta high_threshold) { |
| high_threshold_ = high_threshold; |
| NotifyUpgrade(); |
| } |
| |
| void BroadcastNotificationTypeOverriden(bool overridden) { |
| NotifyRelaunchOverriddenToRequired(overridden); |
| } |
| |
| base::TimeDelta high_threshold() const { return high_threshold_; } |
| |
| private: |
| base::TimeDelta high_threshold_ = base::TimeDelta::FromDays(7); |
| |
| DISALLOW_COPY_AND_ASSIGN(FakeUpgradeDetector); |
| }; |
| |
| } // namespace |
| |
| // A test harness that provides facilities for manipulating the relaunch |
| // notification policy setting and for broadcasting upgrade notifications. |
| class RelaunchNotificationControllerTest : public ::testing::Test { |
| protected: |
| RelaunchNotificationControllerTest() |
| : task_environment_( |
| base::test::TaskEnvironment::TimeSource::MOCK_TIME, |
| base::test::TaskEnvironment::ThreadPoolExecutionMode::QUEUED), |
| scoped_local_state_(TestingBrowserProcess::GetGlobal()), |
| upgrade_detector_(task_environment_.GetMockClock(), |
| task_environment_.GetMockTickClock()) { |
| // Unittests failed when the system is on battery. This class is using a |
| // mock power monitor source `power_monitor_source_` to ensure no real |
| // power state or power notifications are delivered to the unittests. |
| EXPECT_FALSE(base::PowerMonitor::IsOnBatteryPower()); |
| } |
| |
| UpgradeDetector* upgrade_detector() { return &upgrade_detector_; } |
| FakeUpgradeDetector& fake_upgrade_detector() { return upgrade_detector_; } |
| |
| // Sets the browser.relaunch_notification preference in Local State to |
| // |value|. |
| void SetNotificationPref(int value) { |
| scoped_local_state_.Get()->SetManagedPref( |
| prefs::kRelaunchNotification, std::make_unique<base::Value>(value)); |
| } |
| |
| // Returns the TaskEnvironment's MockClock. |
| const base::Clock* GetMockClock() { return task_environment_.GetMockClock(); } |
| |
| // Returns the TaskEnvironment's MockTickClock. |
| const base::TickClock* GetMockTickClock() { |
| return task_environment_.GetMockTickClock(); |
| } |
| |
| // Fast-forwards virtual time by |delta|. |
| void FastForwardBy(base::TimeDelta delta) { |
| task_environment_.FastForwardBy(delta); |
| } |
| |
| void RunUntilIdle() { task_environment_.RunUntilIdle(); } |
| |
| private: |
| // Use a mock power monitor source to ensure the test is in control of the |
| // power notifications. |
| base::test::ScopedPowerMonitorTestSource power_monitor_source_; |
| |
| base::test::TaskEnvironment task_environment_; |
| ScopedTestingLocalState scoped_local_state_; |
| FakeUpgradeDetector upgrade_detector_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RelaunchNotificationControllerTest); |
| }; |
| |
| TEST_F(RelaunchNotificationControllerTest, CreateDestroy) { |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| } |
| |
| // Without the browser.relaunch_notification preference set, the controller |
| // should not be observing the UpgradeDetector, and should therefore never |
| // attempt to show any notifications. |
| |
| // TODO(1004568) Disabled due to race condition. |
| #if defined(THREAD_SANATIZER) |
| #define MAYBE_PolicyUnset DISABLED_PolicyUnset |
| #else |
| #define MAYBE_PolicyUnset PolicyUnset |
| #endif |
| TEST_F(RelaunchNotificationControllerTest, MAYBE_PolicyUnset) { |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_GRACE); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_NONE); |
| } |
| |
| // With the browser.relaunch_notification preference set to 1, the controller |
| // should be observing the UpgradeDetector and should show "Requested" |
| // notifications on each level change above "very low". |
| TEST_F(RelaunchNotificationControllerTest, RecommendedByPolicy) { |
| SetNotificationPref(1); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| // Nothing shown if the level is broadcast at NONE or VERY_LOW. |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_NONE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Show for each level change, but not for repeat notifications. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_GRACE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_GRACE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // First move time to the high annoyance deadline. |
| base::Time high_annoyance_deadline = |
| upgrade_detector()->GetAnnoyanceLevelDeadline( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| FastForwardBy(high_annoyance_deadline - GetMockClock()->Now()); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // The timer should be running to reshow at the detector's delta. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| FastForwardBy(fake_upgrade_detector().GetHighAnnoyanceLevelDelta()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| FastForwardBy(fake_upgrade_detector().GetHighAnnoyanceLevelDelta()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Drop back to elevated to stop the reshows and ensure there are none. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| FastForwardBy(fake_upgrade_detector().GetHighAnnoyanceLevelDelta()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // And closed if the level drops back to very low. |
| EXPECT_CALL(mock_controller_delegate, Close()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Back up to elevated brings the bubble back. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // And it is closed if the level drops back to none. |
| EXPECT_CALL(mock_controller_delegate, Close()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_NONE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_NONE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // With the browser.relaunch_notification preference set to 2, the controller |
| // should be observing the UpgradeDetector and should show "Required" |
| // notifications on each level change. |
| TEST_F(RelaunchNotificationControllerTest, RequiredByPolicy) { |
| SetNotificationPref(2); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| // Nothing shown if the level is broadcast at NONE. |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_NONE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Show for each change to a higher level, but not for repeat notifications. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_GRACE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_GRACE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // And closed if the level drops back to none. |
| EXPECT_CALL(mock_controller_delegate, Close()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_NONE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_NONE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // Flipping the policy should have no effect when at level NONE or VERY_LOW. |
| TEST_F(RelaunchNotificationControllerTest, PolicyChangesNoUpgrade) { |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| SetNotificationPref(1); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(2); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(3); // Bogus value! |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(0); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(1); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(2); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(3); // Bogus value! |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(0); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // Policy changes at an elevated level should show the appropriate notification. |
| TEST_F(RelaunchNotificationControllerTest, PolicyChangesWithUpgrade) { |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| SetNotificationPref(1); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, Close()); |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| SetNotificationPref(2); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, Close()); |
| SetNotificationPref(0); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // Relaunch is forced when the deadline is reached. |
| TEST_F(RelaunchNotificationControllerTest, RequiredDeadlineReached) { |
| SetNotificationPref(2); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| // As in the RequiredByPolicy test, the dialog should be shown. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // And the relaunch should be forced after the deadline passes. |
| EXPECT_CALL(mock_controller_delegate, OnRelaunchDeadlineExpired()); |
| FastForwardBy(fake_upgrade_detector().high_threshold()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // No forced relaunch if the dialog is closed. |
| TEST_F(RelaunchNotificationControllerTest, RequiredDeadlineReachedNoPolicy) { |
| SetNotificationPref(2); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| // As in the RequiredByPolicy test, the dialog should be shown. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // And then closed if the policy is cleared. |
| EXPECT_CALL(mock_controller_delegate, Close()); |
| SetNotificationPref(0); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // And no relaunch should take place. |
| FastForwardBy(fake_upgrade_detector().high_threshold()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // NotificationPeriod changes should do nothing at any policy setting when the |
| // annoyance level is at none. |
| TEST_F(RelaunchNotificationControllerTest, NonePeriodChange) { |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| // Reduce the period. |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| base::TimeDelta::FromDays(1)); |
| FastForwardBy(fake_upgrade_detector().high_threshold()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(1); |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| base::TimeDelta::FromHours(23)); |
| FastForwardBy(fake_upgrade_detector().high_threshold()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(2); |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| base::TimeDelta::FromHours(22)); |
| FastForwardBy(fake_upgrade_detector().high_threshold()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // NotificationPeriod changes should do nothing at any policy setting when the |
| // annoyance level is at very low. |
| TEST_F(RelaunchNotificationControllerTest, VeryLowPeriodChange) { |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Reduce the period. |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| base::TimeDelta::FromDays(1)); |
| FastForwardBy(fake_upgrade_detector().high_threshold()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(1); |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| base::TimeDelta::FromHours(23)); |
| FastForwardBy(fake_upgrade_detector().high_threshold()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(2); |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| base::TimeDelta::FromHours(22)); |
| FastForwardBy(fake_upgrade_detector().high_threshold()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // NotificationPeriod changes impact reshows of the relaunch recommended bubble. |
| TEST_F(RelaunchNotificationControllerTest, PeriodChangeRecommended) { |
| SetNotificationPref(1); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| // First move time to the high annoyance deadline. |
| base::Time high_annoyance_deadline = |
| upgrade_detector()->GetAnnoyanceLevelDeadline( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| FastForwardBy(high_annoyance_deadline - GetMockClock()->Now()); |
| |
| // Get up to high annoyance so that the reshow timer is running. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Advance time partway to the reshow, but not all the way there. |
| FastForwardBy(fake_upgrade_detector().GetHighAnnoyanceLevelDelta() * 0.9); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Now shorten the period dramatically and expect an immediate reshow. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| fake_upgrade_detector().high_threshold() / 10); |
| RunUntilIdle(); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // And expect another reshow at the new delta. |
| base::TimeDelta short_reshow_delta = |
| fake_upgrade_detector().GetHighAnnoyanceLevelDelta(); |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| FastForwardBy(short_reshow_delta); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Now lengthen the period and expect no immediate reshow. |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| fake_upgrade_detector().high_threshold() * 10); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Move forward by the short delta to be sure there's no reshow there. |
| FastForwardBy(short_reshow_delta); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Move forward the rest of the way to the new delta and expect a reshow. |
| base::TimeDelta long_reshow_delta = |
| fake_upgrade_detector().GetHighAnnoyanceLevelDelta(); |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| FastForwardBy(long_reshow_delta - short_reshow_delta); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Similar to the above, move time forward a little bit. |
| FastForwardBy(long_reshow_delta * 0.1); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Shorten the period a bit, but not enough to force a reshow. |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| fake_upgrade_detector().high_threshold() * 0.9); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // And ensure that moving forward the rest of the way to the new delta causes |
| // a reshow. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRecommended()); |
| FastForwardBy(fake_upgrade_detector().GetHighAnnoyanceLevelDelta() - |
| long_reshow_delta * 0.1); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // NotificationPeriod changes impact reshows of the relaunch required dialog. |
| TEST_F(RelaunchNotificationControllerTest, PeriodChangeRequired) { |
| SetNotificationPref(2); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Move forward partway to the current deadline. Nothing should happen. |
| base::Time high_annoyance_deadline = |
| upgrade_detector()->GetAnnoyanceLevelDeadline( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| FastForwardBy((high_annoyance_deadline - GetMockClock()->Now()) / 2); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Lengthen the period, thereby pushing out the deadline. |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| fake_upgrade_detector().high_threshold() * 2); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Ensure that nothing happens when the old deadline passes. |
| FastForwardBy(high_annoyance_deadline - GetMockClock()->Now()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Now we enter elevated annoyance level and show the dialog. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Now we enter grace annoyance level and again show the dialog. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_GRACE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Jumping to the new deadline relaunches the browser. |
| EXPECT_CALL(mock_controller_delegate, OnRelaunchDeadlineExpired()); |
| FastForwardBy(upgrade_detector()->GetAnnoyanceLevelDeadline( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH) - |
| GetMockClock()->Now()); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Shorten the period, bringing in the deadline. Expect the dialog to show and |
| // a relaunch after the grace period passes. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| fake_upgrade_detector().high_threshold() / 2); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| EXPECT_CALL(mock_controller_delegate, OnRelaunchDeadlineExpired()); |
| FastForwardBy(FakeRelaunchNotificationController::kRelaunchGracePeriod); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // Test that grace period is given to the user to relaunch if the deadline is |
| // shortened to be in the past due to change in notification period. |
| TEST_F(RelaunchNotificationControllerTest, DeadlineShortenGracePeriod) { |
| SetNotificationPref(2); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Move forward partway to the current deadline. Nothing should happen. |
| base::Time high_annoyance_deadline = |
| upgrade_detector()->GetAnnoyanceLevelDeadline( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| FastForwardBy((high_annoyance_deadline - GetMockClock()->Now()) / 2); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Shorten the period, thereby pushing the deadline in the past. Expect the |
| // dialog to show and a relaunch after the grace period passes. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastHighThresholdChange( |
| fake_upgrade_detector().high_threshold() / 3); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| EXPECT_CALL(mock_controller_delegate, OnRelaunchDeadlineExpired()); |
| FastForwardBy(FakeRelaunchNotificationController::kRelaunchGracePeriod); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // Test that grace period is given to the user to relaunch if the device goes to |
| // sleep beyond the deadline before showing the notification. |
| TEST_F(RelaunchNotificationControllerTest, DeviceSleepBeforeNotification) { |
| SetNotificationPref(2); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_VERY_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Assume device goes to sleep beyond the deadline. |
| base::Time high_annoyance_deadline = |
| upgrade_detector()->GetAnnoyanceLevelDeadline( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| FastForwardBy((high_annoyance_deadline - GetMockClock()->Now()) * 1.2); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // As device awakes high annoyance is notified. Expect the |
| // dialog to show and a relaunch after the grace period passes. |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| EXPECT_CALL(mock_controller_delegate, OnRelaunchDeadlineExpired()); |
| FastForwardBy(FakeRelaunchNotificationController::kRelaunchGracePeriod); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // Test that the deadline is extended by the grace period when the |
| // notification is potentially seen. |
| TEST_F(RelaunchNotificationControllerTest, DeferredRequired) { |
| SetNotificationPref(2); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Move time just before the original deadline. |
| FastForwardBy(fake_upgrade_detector().high_threshold() - |
| 0.5 * FakeRelaunchNotificationController::kRelaunchGracePeriod); |
| |
| // Suddenly, the UX becomes available. |
| base::Time deadline = controller.IncreaseRelaunchDeadlineOnShow(); |
| ASSERT_EQ(deadline, |
| GetMockClock()->Now() + |
| FakeRelaunchNotificationController::kRelaunchGracePeriod); |
| |
| // And the relaunch is extended by the grace period. |
| EXPECT_CALL(mock_controller_delegate, OnRelaunchDeadlineExpired()); |
| FastForwardBy(FakeRelaunchNotificationController::kRelaunchGracePeriod); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // Call to override the current relaunch notification type should override it to |
| // required and policy change should not affect it. |
| TEST_F(RelaunchNotificationControllerTest, OverriddenToRequired) { |
| SetNotificationPref(1); |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| fake_upgrade_detector().BroadcastNotificationTypeOverriden(true); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| SetNotificationPref(0); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, Close()); |
| fake_upgrade_detector().BroadcastNotificationTypeOverriden(false); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| // Tests that the required notification is shown all three times when the clock |
| // moves along with the elevations. |
| TEST_F(RelaunchNotificationControllerTest, NotifyAllWithShortestPeriod) { |
| SetNotificationPref(2); |
| |
| ::testing::StrictMock<MockControllerDelegate> mock_controller_delegate; |
| FakeRelaunchNotificationController controller( |
| upgrade_detector(), GetMockClock(), GetMockTickClock(), |
| &mock_controller_delegate); |
| |
| // Advance to the low threshold and raise the annoyance level. |
| const auto delta = fake_upgrade_detector().high_threshold() / 3; |
| FastForwardBy(delta); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_LOW); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Advance to the elevated threshold and raise the annoyance level. |
| FastForwardBy(fake_upgrade_detector().high_threshold() - delta * 2); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_ELEVATED); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Advance to the grace threshold and raise the annoyance level. |
| FastForwardBy(delta - base::TimeDelta::FromHours(1)); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_GRACE); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| EXPECT_CALL(mock_controller_delegate, NotifyRelaunchRequired()); |
| fake_upgrade_detector().BroadcastLevelChange( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| |
| // Advance to the deadline to restart. |
| EXPECT_CALL(mock_controller_delegate, OnRelaunchDeadlineExpired()); |
| FastForwardBy(base::TimeDelta::FromHours(1)); |
| ASSERT_EQ(GetMockClock()->Now(), |
| upgrade_detector()->GetAnnoyanceLevelDeadline( |
| UpgradeDetector::UPGRADE_ANNOYANCE_HIGH)); |
| ::testing::Mock::VerifyAndClearExpectations(&mock_controller_delegate); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| class RelaunchNotificationControllerPlatformImplTest : public ::testing::Test { |
| protected: |
| RelaunchNotificationControllerPlatformImplTest() |
| : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} |
| |
| ~RelaunchNotificationControllerPlatformImplTest() override = default; |
| |
| void SetUp() override { |
| ash::AshTestHelper::InitParams init_params; |
| init_params.start_session = false; |
| ash_test_helper_.SetUp(std::move(init_params)); |
| |
| user_manager_ = new ash::FakeChromeUserManager(); |
| scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( |
| base::WrapUnique(user_manager_)); |
| |
| const char test_user_email[] = "test_user@example.com"; |
| const AccountId test_account_id(AccountId::FromUserEmail(test_user_email)); |
| user_manager_->AddUser(test_account_id); |
| user_manager_->LoginUser(test_account_id); |
| session_manager_.CreateSession(test_account_id, test_user_email, false); |
| session_manager_.SetSessionState(session_manager::SessionState::ACTIVE); |
| |
| logger_ = std::make_unique<display::test::ActionLogger>(); |
| native_display_delegate_ = |
| new display::test::TestNativeDisplayDelegate(logger_.get()); |
| ash::Shell::Get()->display_configurator()->SetDelegateForTesting( |
| std::unique_ptr<display::NativeDisplayDelegate>( |
| native_display_delegate_)); |
| } |
| |
| void LockScreen() { |
| session_manager_.SetSessionState(session_manager::SessionState::LOCKED); |
| } |
| |
| void UnLockScreen() { |
| session_manager_.SetSessionState(session_manager::SessionState::ACTIVE); |
| } |
| |
| void TurnDisplayOff() { |
| ash::Shell::Get()->display_configurator()->SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_OFF, 0, base::DoNothing()); |
| } |
| |
| void TurnDisplayOn() { |
| ash::Shell::Get()->display_configurator()->SetDisplayPower( |
| chromeos::DISPLAY_POWER_ALL_ON, 0, base::DoNothing()); |
| } |
| |
| RelaunchNotificationControllerPlatformImpl& platform_impl() { return impl_; } |
| |
| // Returns the TaskEnvironment's MockClock. |
| const base::Clock* GetMockClock() { return task_environment_.GetMockClock(); } |
| |
| private: |
| content::BrowserTaskEnvironment task_environment_; |
| RelaunchNotificationControllerPlatformImpl impl_; |
| ash::AshTestHelper ash_test_helper_; |
| session_manager::SessionManager session_manager_; |
| ash::FakeChromeUserManager* user_manager_; |
| std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; |
| std::unique_ptr<display::test::ActionLogger> logger_; |
| display::NativeDisplayDelegate* native_display_delegate_; |
| }; |
| |
| // SynchronousNotification |
| TEST_F(RelaunchNotificationControllerPlatformImplTest, |
| SynchronousNotification) { |
| UnLockScreen(); |
| TurnDisplayOn(); |
| |
| // Expect the platform_impl to query for the deadline synchronously. |
| ::testing::StrictMock<base::MockOnceCallback<base::Time()>> callback; |
| platform_impl().NotifyRelaunchRequired(GetMockClock()->Now(), callback.Get()); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| } |
| |
| // Deferred Notification when the display is off then on. |
| TEST_F(RelaunchNotificationControllerPlatformImplTest, |
| DeferredNotificationDisplayOff) { |
| TurnDisplayOff(); |
| |
| ::testing::StrictMock<base::MockOnceCallback<base::Time()>> callback; |
| |
| platform_impl().NotifyRelaunchRequired(GetMockClock()->Now(), callback.Get()); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| |
| EXPECT_CALL(callback, Run()); |
| TurnDisplayOn(); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| } |
| |
| // Deferred Notification when the display is off then on. |
| TEST_F(RelaunchNotificationControllerPlatformImplTest, |
| DeferredNotificationSessionLocked) { |
| LockScreen(); |
| |
| ::testing::StrictMock<base::MockOnceCallback<base::Time()>> callback; |
| |
| platform_impl().NotifyRelaunchRequired(GetMockClock()->Now(), callback.Get()); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| |
| EXPECT_CALL(callback, Run()); |
| UnLockScreen(); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| } |
| |
| // Multiple screen on & off. |
| TEST_F(RelaunchNotificationControllerPlatformImplTest, |
| RequiredDeadlineReachedAfterMultipleResume) { |
| TurnDisplayOff(); |
| |
| ::testing::StrictMock<base::MockOnceCallback<base::Time()>> callback; |
| |
| platform_impl().NotifyRelaunchRequired(GetMockClock()->Now(), callback.Get()); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| |
| EXPECT_CALL(callback, Run()); |
| TurnDisplayOn(); |
| |
| TurnDisplayOff(); |
| TurnDisplayOn(); |
| TurnDisplayOff(); |
| TurnDisplayOn(); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| } |
| |
| // Multiple session locks & unlocks. |
| TEST_F(RelaunchNotificationControllerPlatformImplTest, |
| RequiredDeadlineReachedBeforeMultipleUnlock) { |
| LockScreen(); |
| |
| ::testing::StrictMock<base::MockOnceCallback<base::Time()>> callback; |
| |
| platform_impl().NotifyRelaunchRequired(GetMockClock()->Now(), callback.Get()); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| |
| EXPECT_CALL(callback, Run()); |
| UnLockScreen(); |
| |
| LockScreen(); |
| UnLockScreen(); |
| LockScreen(); |
| UnLockScreen(); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| } |
| |
| #else // BUILDFLAG(IS_CHROMEOS_ASH) |
| |
| class RelaunchNotificationControllerPlatformImplTest |
| : public TestWithBrowserView { |
| protected: |
| RelaunchNotificationControllerPlatformImplTest() : TestWithBrowserView() {} |
| |
| void SetUp() override { |
| TestWithBrowserView::SetUp(); |
| impl_.emplace(); |
| } |
| |
| void SetVisibility(bool is_visible) { |
| if (is_visible) |
| browser_view()->Show(); |
| else |
| browser_view()->Hide(); |
| |
| // Allow UI tasks to run so that the browser becomes fully active/inactive. |
| task_environment()->RunUntilIdle(); |
| } |
| |
| RelaunchNotificationControllerPlatformImpl& platform_impl() { return *impl_; } |
| |
| private: |
| absl::optional<RelaunchNotificationControllerPlatformImpl> impl_; |
| }; |
| |
| TEST_F(RelaunchNotificationControllerPlatformImplTest, |
| SynchronousNotification) { |
| // Make the UX visible to the user so that no delay will be incurred |
| ASSERT_NO_FATAL_FAILURE(SetVisibility(true)); |
| |
| // Expect the platform_impl to show the notification synchronously. |
| ::testing::StrictMock<base::MockOnceCallback<base::Time()>> callback; |
| |
| base::Time deadline = |
| base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromHours(1)); |
| |
| // There should be no query at the time of showing. |
| platform_impl().NotifyRelaunchRequired(deadline, callback.Get()); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| |
| ASSERT_NO_FATAL_FAILURE(SetVisibility(false)); |
| |
| // There should be no query because the browser isn't visible. |
| platform_impl().NotifyRelaunchRequired(deadline, callback.Get()); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| |
| // There should be no query because this isn't the first time to show the |
| // notification. |
| ASSERT_NO_FATAL_FAILURE(SetVisibility(true)); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| } |
| |
| TEST_F(RelaunchNotificationControllerPlatformImplTest, DeferredDeadline) { |
| ::testing::StrictMock<base::MockOnceCallback<base::Time()>> callback; |
| |
| base::Time deadline = |
| base::Time::FromDeltaSinceWindowsEpoch(base::TimeDelta::FromHours(1)); |
| |
| // There should be no query because the browser isn't visible. |
| platform_impl().NotifyRelaunchRequired(deadline, callback.Get()); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| |
| // The query should happen once the notification is potentially seen. |
| EXPECT_CALL(callback, Run()).WillOnce(Return(deadline)); |
| ASSERT_NO_FATAL_FAILURE(SetVisibility(true)); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| |
| ASSERT_NO_FATAL_FAILURE(SetVisibility(false)); |
| |
| // There should be no query because the browser isn't visible. |
| platform_impl().NotifyRelaunchRequired(deadline, callback.Get()); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| |
| // There should be no query because this isn't the first time to show the |
| // notification. |
| ASSERT_NO_FATAL_FAILURE(SetVisibility(true)); |
| ::testing::Mock::VerifyAndClearExpectations(&callback); |
| } |
| |
| #endif // BUILDFLAG(IS_CHROMEOS_ASH) |