blob: 63106399d39d8f80fba5e8990e6b20109c292bfe [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/chromeos/policy/minimum_version_policy_handler.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "base/time/default_clock.h"
#include "base/values.h"
#include "chrome/browser/chromeos/policy/minimum_version_policy_test_helpers.h"
#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h"
#include "chrome/browser/notifications/notification_display_service_tester.h"
#include "chrome/browser/notifications/system_notification_helper.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 "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_update_engine_client.h"
#include "chromeos/dbus/shill/shill_service_client.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/settings/cros_settings_names.h"
#include "chromeos/tpm/stub_install_attributes.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
using testing::_;
using testing::Mock;
using MinimumVersionRequirement =
policy::MinimumVersionPolicyHandler::MinimumVersionRequirement;
namespace chromeos {
namespace {
const char kFakeCurrentVersion[] = "13305.20.0";
const char kNewVersion[] = "13305.25.0";
const char kUpdateRequiredNotificationId[] = "policy.update_required";
const char kCellularServicePath[] = "/service/cellular1";
const int kLongWarningInDays = 10;
const int kShortWarningInDays = 2;
} // namespace
class UpdateRequiredNotificationTest
: public testing::Test,
public policy::MinimumVersionPolicyHandler::Delegate {
public:
UpdateRequiredNotificationTest();
void SetUp() override;
void TearDown() override;
// MinimumVersionPolicyHandler::Delegate:
base::Version GetCurrentVersion() const;
bool IsUserEnterpriseManaged() const;
MOCK_METHOD0(ShowUpdateRequiredScreen, void());
MOCK_METHOD0(RestartToLoginScreen, void());
MOCK_METHOD0(HideUpdateRequiredScreenIfShown, void());
MOCK_CONST_METHOD0(IsLoginSessionState, bool());
MOCK_CONST_METHOD0(IsKioskMode, bool());
MOCK_CONST_METHOD0(IsLoginInProgress, bool());
MOCK_CONST_METHOD0(IsEnterpriseManaged, bool());
MOCK_CONST_METHOD0(IsUserLoggedIn, bool());
void SetCurrentVersionString(const std::string& version);
void CreateMinimumVersionHandler();
const MinimumVersionRequirement* GetState() const;
// Set new value for policy pref.
void SetPolicyPref(base::Value value);
void VerifyUpdateRequiredNotification(const base::string16& expected_title,
const base::string16& expected_message);
policy::MinimumVersionPolicyHandler* GetMinimumVersionPolicyHandler() {
return minimum_version_policy_handler_.get();
}
NotificationDisplayServiceTester* display_service() {
return notification_service_.get();
}
chromeos::FakeUpdateEngineClient* update_engine() {
return fake_update_engine_client_;
}
void SetUserManaged(bool managed) { user_managed_ = managed; }
content::BrowserTaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
private:
bool user_managed_ = true;
ScopedTestingLocalState local_state_;
chromeos::ScopedTestingCrosSettings scoped_testing_cros_settings_;
std::unique_ptr<NotificationDisplayServiceTester> notification_service_;
chromeos::ScopedStubInstallAttributes scoped_stub_install_attributes_;
chromeos::FakeUpdateEngineClient* fake_update_engine_client_;
std::unique_ptr<base::Version> current_version_;
std::unique_ptr<policy::MinimumVersionPolicyHandler>
minimum_version_policy_handler_;
};
UpdateRequiredNotificationTest::UpdateRequiredNotificationTest()
: local_state_(TestingBrowserProcess::GetGlobal()) {
ON_CALL(*this, IsEnterpriseManaged).WillByDefault(testing::Return(true));
ON_CALL(*this, IsUserLoggedIn).WillByDefault(testing::Return(true));
}
void UpdateRequiredNotificationTest::SetUp() {
auto fake_update_engine_client =
std::make_unique<chromeos::FakeUpdateEngineClient>();
fake_update_engine_client_ = fake_update_engine_client.get();
chromeos::DBusThreadManager::GetSetterForTesting()->SetUpdateEngineClient(
std::move(fake_update_engine_client));
chromeos::NetworkHandler::Initialize();
chromeos::ShillServiceClient::TestInterface* service_test =
chromeos::DBusThreadManager::Get()
->GetShillServiceClient()
->GetTestInterface();
service_test->ClearServices();
service_test->AddService("/service/eth", "eth" /* guid */, "eth",
shill::kTypeEthernet, shill::kStateOnline,
true /* visible */);
base::RunLoop().RunUntilIdle();
scoped_stub_install_attributes_.Get()->SetCloudManaged("managed.com",
"device_id");
TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper(
std::make_unique<SystemNotificationHelper>());
notification_service_ =
std::make_unique<NotificationDisplayServiceTester>(nullptr /*profile*/);
CreateMinimumVersionHandler();
SetCurrentVersionString(kFakeCurrentVersion);
}
void UpdateRequiredNotificationTest::TearDown() {
minimum_version_policy_handler_.reset();
chromeos::NetworkHandler::Shutdown();
}
void UpdateRequiredNotificationTest::CreateMinimumVersionHandler() {
minimum_version_policy_handler_.reset(new policy::MinimumVersionPolicyHandler(
this, chromeos::CrosSettings::Get()));
}
const MinimumVersionRequirement* UpdateRequiredNotificationTest::GetState()
const {
return minimum_version_policy_handler_->GetState();
}
void UpdateRequiredNotificationTest::SetCurrentVersionString(
const std::string& version) {
current_version_.reset(new base::Version(version));
ASSERT_TRUE(current_version_->IsValid());
}
bool UpdateRequiredNotificationTest::IsUserEnterpriseManaged() const {
return user_managed_;
}
base::Version UpdateRequiredNotificationTest::GetCurrentVersion() const {
return *current_version_;
}
void UpdateRequiredNotificationTest::SetPolicyPref(base::Value value) {
scoped_testing_cros_settings_.device_settings()->Set(
chromeos::kDeviceMinimumVersion, value);
}
void UpdateRequiredNotificationTest::VerifyUpdateRequiredNotification(
const base::string16& expected_title,
const base::string16& expected_message) {
auto notification =
display_service()->GetNotification(kUpdateRequiredNotificationId);
ASSERT_TRUE(notification);
EXPECT_EQ(notification->title(), expected_title);
EXPECT_EQ(notification->message(), expected_message);
}
TEST_F(UpdateRequiredNotificationTest, NoNetworkNotifications) {
EXPECT_TRUE(GetMinimumVersionPolicyHandler()->RequirementsAreSatisfied());
// Disconnect all networks
chromeos::ShillServiceClient::TestInterface* service_test =
chromeos::DBusThreadManager::Get()
->GetShillServiceClient()
->GetTestInterface();
service_test->ClearServices();
// This is needed to wait till EOL status is fetched from the update_engine.
base::RunLoop run_loop;
GetMinimumVersionPolicyHandler()->set_fetch_eol_callback_for_testing(
run_loop.QuitClosure());
// Create and set pref value to invoke policy handler.
SetPolicyPref(policy::CreateMinimumVersionSingleRequirementPolicyValue(
kNewVersion, kLongWarningInDays, kLongWarningInDays,
false /* unmanaged_user_restricted */));
run_loop.Run();
EXPECT_TRUE(
GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting());
EXPECT_FALSE(GetMinimumVersionPolicyHandler()->RequirementsAreSatisfied());
// Check notification is shown for offline devices with the warning time.
base::string16 expected_title =
base::ASCIIToUTF16("Update Chrome device within 10 days");
base::string16 expected_message = base::ASCIIToUTF16(
"managed.com requires you to download an update before the deadline. The "
"update will download automatically when you connect to the internet.");
VerifyUpdateRequiredNotification(expected_title, expected_message);
// Expire the notification timer to show new notification on the last day.
const base::TimeDelta warning =
base::TimeDelta::FromDays(kLongWarningInDays - 1);
task_environment_.FastForwardBy(warning);
base::string16 expected_title_last_day =
base::ASCIIToUTF16("Last day to update Chrome device");
base::string16 expected_message_last_day = base::ASCIIToUTF16(
"managed.com requires you to download an update today. The "
"update will download automatically when you connect to the internet.");
VerifyUpdateRequiredNotification(expected_title_last_day,
expected_message_last_day);
}
TEST_F(UpdateRequiredNotificationTest, MeteredNetworkNotifications) {
// Connect to metered network
chromeos::ShillServiceClient::TestInterface* service_test =
chromeos::DBusThreadManager::Get()
->GetShillServiceClient()
->GetTestInterface();
service_test->ClearServices();
service_test->AddService(kCellularServicePath,
kCellularServicePath /* guid */,
kCellularServicePath, shill::kTypeCellular,
shill::kStateOnline, true /* visible */);
base::RunLoop().RunUntilIdle();
// This is needed to wait till EOL status is fetched from the update_engine.
base::RunLoop run_loop;
GetMinimumVersionPolicyHandler()->set_fetch_eol_callback_for_testing(
run_loop.QuitClosure());
// Create and set pref value to invoke policy handler.
SetPolicyPref(policy::CreateMinimumVersionSingleRequirementPolicyValue(
kNewVersion, kLongWarningInDays, kLongWarningInDays,
false /* unmanaged_user_restricted */));
run_loop.Run();
EXPECT_TRUE(
GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting());
// Check notification is shown for metered network with the warning time.
base::string16 expected_title =
base::ASCIIToUTF16("Update Chrome device within 10 days");
base::string16 expected_message = base::ASCIIToUTF16(
"managed.com requires you to connect to Wi-Fi and download an update "
"before the deadline. Or, download from a metered connection (charges "
"may apply).");
VerifyUpdateRequiredNotification(expected_title, expected_message);
// Expire the notification timer to show new notification on the last day.
const base::TimeDelta warning =
base::TimeDelta::FromDays(kLongWarningInDays - 1);
task_environment_.FastForwardBy(warning);
base::string16 expected_title_last_day =
base::ASCIIToUTF16("Last day to update Chrome device");
base::string16 expected_message_last_day = base::ASCIIToUTF16(
"managed.com requires you to connect to Wi-Fi today to download an "
"update. Or, download from a metered connection (charges may apply).");
VerifyUpdateRequiredNotification(expected_title_last_day,
expected_message_last_day);
}
TEST_F(UpdateRequiredNotificationTest, EolNotifications) {
// Set device state to end of life.
update_engine()->set_eol_date(base::DefaultClock::GetInstance()->Now() -
base::TimeDelta::FromDays(1));
// This is needed to wait till EOL status is fetched from the update_engine.
base::RunLoop run_loop;
GetMinimumVersionPolicyHandler()->set_fetch_eol_callback_for_testing(
run_loop.QuitClosure());
// Create and set pref value to invoke policy handler.
SetPolicyPref(policy::CreateMinimumVersionSingleRequirementPolicyValue(
kNewVersion, kLongWarningInDays, kLongWarningInDays,
false /* unmanaged_user_restricted */));
run_loop.Run();
EXPECT_TRUE(
GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting());
// Check notification is shown for end of life with the warning time.
base::string16 expected_title =
base::ASCIIToUTF16("Return Chrome device within 10 days");
base::string16 expected_message = base::ASCIIToUTF16(
"managed.com requires you to back up your data and return this Chrome "
"device before the deadline.");
VerifyUpdateRequiredNotification(expected_title, expected_message);
// Expire notification timer to show new notification a week before deadline.
const base::TimeDelta warning =
base::TimeDelta::FromDays(kLongWarningInDays - 7);
task_environment_.FastForwardBy(warning);
base::string16 expected_title_one_week =
base::ASCIIToUTF16("Return Chrome device within 1 week");
VerifyUpdateRequiredNotification(expected_title_one_week, expected_message);
// Expire the notification timer to show new notification on the last day.
const base::TimeDelta warning_last_day = base::TimeDelta::FromDays(6);
task_environment_.FastForwardBy(warning_last_day);
base::string16 expected_title_last_day =
base::ASCIIToUTF16("Immediate return required");
base::string16 expected_message_last_day = base::ASCIIToUTF16(
"managed.com requires you to back up your data and return this Chrome "
"device today.");
VerifyUpdateRequiredNotification(expected_title_last_day,
expected_message_last_day);
}
TEST_F(UpdateRequiredNotificationTest, LastHourEolNotifications) {
// Set device state to end of life.
update_engine()->set_eol_date(base::DefaultClock::GetInstance()->Now() -
base::TimeDelta::FromDays(kLongWarningInDays));
// Set local state to simulate update required timer running and one hour to
// deadline.
PrefService* prefs = g_browser_process->local_state();
const base::TimeDelta delta = base::TimeDelta::FromDays(kShortWarningInDays) -
base::TimeDelta::FromHours(1);
prefs->SetTime(prefs::kUpdateRequiredTimerStartTime,
base::Time::Now() - delta);
prefs->SetTimeDelta(prefs::kUpdateRequiredWarningPeriod,
base::TimeDelta::FromDays(kShortWarningInDays));
// This is needed to wait till EOL status is fetched from the update_engine.
base::RunLoop run_loop;
GetMinimumVersionPolicyHandler()->set_fetch_eol_callback_for_testing(
run_loop.QuitClosure());
// Create and set pref value to invoke policy handler.
SetPolicyPref(policy::CreateMinimumVersionSingleRequirementPolicyValue(
kNewVersion, kShortWarningInDays, kShortWarningInDays,
false /* unmanaged_user_restricted */));
run_loop.Run();
EXPECT_TRUE(
GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting());
base::string16 expected_title_last_day =
base::ASCIIToUTF16("Immediate return required");
base::string16 expected_message_last_day = base::ASCIIToUTF16(
"managed.com requires you to back up your data and return this Chrome "
"device today.");
VerifyUpdateRequiredNotification(expected_title_last_day,
expected_message_last_day);
}
TEST_F(UpdateRequiredNotificationTest, ChromeboxNotifications) {
base::SysInfo::SetChromeOSVersionInfoForTest("DEVICETYPE=CHROMEBOX",
base::Time::Now());
// Set device state to end of life reached.
update_engine()->set_eol_date(base::DefaultClock::GetInstance()->Now() -
base::TimeDelta::FromDays(kLongWarningInDays));
// This is needed to wait till EOL status is fetched from the update_engine.
base::RunLoop run_loop;
GetMinimumVersionPolicyHandler()->set_fetch_eol_callback_for_testing(
run_loop.QuitClosure());
// Create and set pref value to invoke policy handler.
SetPolicyPref(policy::CreateMinimumVersionSingleRequirementPolicyValue(
kNewVersion, kLongWarningInDays, kLongWarningInDays,
false /* unmanaged_user_restricted */));
run_loop.Run();
EXPECT_TRUE(
GetMinimumVersionPolicyHandler()->IsDeadlineTimerRunningForTesting());
// Check Chromebox notification is shown for end of life with the warning
// time.
base::string16 expected_title =
base::ASCIIToUTF16("Return Chromebox within 10 days");
base::string16 expected_message = base::ASCIIToUTF16(
"managed.com requires you to back up your data and return this Chromebox "
"before the deadline.");
VerifyUpdateRequiredNotification(expected_title, expected_message);
// Expire notification timer to show new notification a week before deadline.
const base::TimeDelta warning =
base::TimeDelta::FromDays(kLongWarningInDays - 7);
task_environment_.FastForwardBy(warning);
base::string16 expected_title_one_week =
base::ASCIIToUTF16("Return Chromebox within 1 week");
VerifyUpdateRequiredNotification(expected_title_one_week, expected_message);
}
} // namespace chromeos