1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/policy/tpm_auto_update_mode_policy_handler.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/callback_helpers.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/run_loop.h"
13 #include "base/timer/mock_timer.h"
14 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
15 #include "chrome/browser/chromeos/settings/scoped_testing_cros_settings.h"
16 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
17 #include "chrome/browser/chromeos/tpm_firmware_update.h"
18 #include "chrome/browser/prefs/browser_prefs.h"
19 #include "chrome/common/pref_names.h"
20 #include "chrome/test/base/scoped_testing_local_state.h"
21 #include "chrome/test/base/testing_browser_process.h"
22 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "chromeos/dbus/session_manager/fake_session_manager_client.h"
24 #include "chromeos/settings/cros_settings_names.h"
25 #include "chromeos/tpm/stub_install_attributes.h"
26 #include "components/account_id/account_id.h"
27 #include "components/prefs/pref_service.h"
28 #include "components/prefs/testing_pref_service.h"
29 #include "components/user_manager/fake_user_manager.h"
30 #include "components/user_manager/scoped_user_manager.h"
31 #include "content/public/test/browser_task_environment.h"
32 #include "testing/gtest/include/gtest/gtest.h"
33
34 namespace {
35 constexpr char kFakeUserName[] = "test@example.com";
36 constexpr char kFakeGaiaId[] = "1234567890";
37 } // namespace
38
39 namespace policy {
40
41 class TPMAutoUpdateModePolicyHandlerTest : public testing::Test {
42 public:
TPMAutoUpdateModePolicyHandlerTest()43 TPMAutoUpdateModePolicyHandlerTest()
44 : local_state_(TestingBrowserProcess::GetGlobal()),
45 user_manager_(new chromeos::FakeChromeUserManager()),
46 user_manager_enabler_(base::WrapUnique(user_manager_)) {
47 chromeos::SessionManagerClient::InitializeFakeInMemory();
48 }
49
~TPMAutoUpdateModePolicyHandlerTest()50 ~TPMAutoUpdateModePolicyHandlerTest() override {
51 chromeos::SessionManagerClient::Shutdown();
52 }
53
SetAutoUpdateMode(AutoUpdateMode auto_update_mode)54 void SetAutoUpdateMode(AutoUpdateMode auto_update_mode) {
55 base::DictionaryValue dict;
56 dict.SetKey(chromeos::tpm_firmware_update::kSettingsKeyAutoUpdateMode,
57 base::Value(static_cast<int>(auto_update_mode)));
58 scoped_testing_cros_settings_.device_settings()->Set(
59 chromeos::kTPMFirmwareUpdateSettings, dict);
60 base::RunLoop().RunUntilIdle();
61 }
62
CheckForUpdate(base::OnceCallback<void (bool)> callback)63 void CheckForUpdate(base::OnceCallback<void(bool)> callback) {
64 std::move(callback).Run(update_available_);
65 }
66
ShowNotification(chromeos::TpmAutoUpdateUserNotification notification_type)67 void ShowNotification(
68 chromeos::TpmAutoUpdateUserNotification notification_type) {
69 last_shown_notification_ = notification_type;
70 }
71
72 protected:
73 bool update_available_ = false;
74 chromeos::TpmAutoUpdateUserNotification last_shown_notification_ =
75 chromeos::TpmAutoUpdateUserNotification::kNone;
76
77 content::BrowserTaskEnvironment task_environment_;
78 ScopedTestingLocalState local_state_;
79 chromeos::FakeChromeUserManager* user_manager_;
80 user_manager::ScopedUserManager user_manager_enabler_;
81
82 // Set up fake install attributes to pretend the machine is enrolled.
83 chromeos::ScopedStubInstallAttributes test_install_attributes_{
84 chromeos::StubInstallAttributes::CreateCloudManaged("example.com",
85 "fake-id")};
86 chromeos::ScopedTestingCrosSettings scoped_testing_cros_settings_;
87
88 base::WeakPtrFactory<TPMAutoUpdateModePolicyHandlerTest> weak_factory_{this};
89 };
90
91 // Verify if the TPM updates are triggered (or not) according to the device
92 // policy option TPMFirmwareUpdateSettings.AutoUpdateMode.
TEST_F(TPMAutoUpdateModePolicyHandlerTest,PolicyUpdatesTriggered)93 TEST_F(TPMAutoUpdateModePolicyHandlerTest, PolicyUpdatesTriggered) {
94 TPMAutoUpdateModePolicyHandler tpm_update_policy_handler(
95 chromeos::CrosSettings::Get(), local_state_.Get());
96 tpm_update_policy_handler.SetUpdateCheckerCallbackForTesting(
97 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::CheckForUpdate,
98 weak_factory_.GetWeakPtr()));
99
100 update_available_ = true;
101
102 auto* fake_session_manager_client = chromeos::FakeSessionManagerClient::Get();
103
104 base::RunLoop().RunUntilIdle();
105 EXPECT_EQ(
106 0, fake_session_manager_client->start_tpm_firmware_update_call_count());
107
108 SetAutoUpdateMode(AutoUpdateMode::kWithoutAcknowledgment);
109 base::RunLoop().RunUntilIdle();
110 EXPECT_EQ(
111 1, fake_session_manager_client->start_tpm_firmware_update_call_count());
112
113 SetAutoUpdateMode(AutoUpdateMode::kNever);
114 base::RunLoop().RunUntilIdle();
115 EXPECT_EQ(
116 1, fake_session_manager_client->start_tpm_firmware_update_call_count());
117
118 SetAutoUpdateMode(AutoUpdateMode::kWithoutAcknowledgment);
119 base::RunLoop().RunUntilIdle();
120 EXPECT_EQ(
121 2, fake_session_manager_client->start_tpm_firmware_update_call_count());
122
123 SetAutoUpdateMode(AutoUpdateMode::kEnrollment);
124 base::RunLoop().RunUntilIdle();
125 EXPECT_EQ(
126 2, fake_session_manager_client->start_tpm_firmware_update_call_count());
127 }
128
129 // Verify that the DBus call to start TPM firmware update is not triggered if
130 // state preserving update is not available.
TEST_F(TPMAutoUpdateModePolicyHandlerTest,NoUpdatesAvailable)131 TEST_F(TPMAutoUpdateModePolicyHandlerTest, NoUpdatesAvailable) {
132 TPMAutoUpdateModePolicyHandler tpm_update_policy_handler(
133 chromeos::CrosSettings::Get(), local_state_.Get());
134 tpm_update_policy_handler.SetUpdateCheckerCallbackForTesting(
135 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::CheckForUpdate,
136 weak_factory_.GetWeakPtr()));
137
138 update_available_ = false;
139
140 SetAutoUpdateMode(AutoUpdateMode::kWithoutAcknowledgment);
141 base::RunLoop().RunUntilIdle();
142 EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
143 ->start_tpm_firmware_update_call_count());
144 }
145
146 // Verify that the notification informing the user that an update is planned
147 // after 24 hours is shown.
TEST_F(TPMAutoUpdateModePolicyHandlerTest,ShowPlannedUpdateNotification)148 TEST_F(TPMAutoUpdateModePolicyHandlerTest, ShowPlannedUpdateNotification) {
149 TPMAutoUpdateModePolicyHandler tpm_update_policy_handler(
150 chromeos::CrosSettings::Get(), local_state_.Get());
151 tpm_update_policy_handler.SetUpdateCheckerCallbackForTesting(
152 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::CheckForUpdate,
153 weak_factory_.GetWeakPtr()));
154 tpm_update_policy_handler.SetShowNotificationCallbackForTesting(
155 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::ShowNotification,
156 base::Unretained(this)));
157
158 const AccountId account_id(
159 AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId));
160 user_manager_->AddUser(account_id);
161 user_manager_->LoginUser(account_id);
162
163 update_available_ = true;
164
165 EXPECT_EQ(last_shown_notification_,
166 chromeos::TpmAutoUpdateUserNotification::kNone);
167
168 SetAutoUpdateMode(AutoUpdateMode::kUserAcknowledgment);
169 base::RunLoop().RunUntilIdle();
170
171 // TPM update is not triggered.
172 EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
173 ->start_tpm_firmware_update_call_count());
174
175 EXPECT_EQ(last_shown_notification_,
176 chromeos::TpmAutoUpdateUserNotification::kPlanned);
177 }
178
179 // Verify that the notification informing the user that an update will happen at
180 // the next reboot is shown.
TEST_F(TPMAutoUpdateModePolicyHandlerTest,ShowUpdateOnRebootNotificationNoTimer)181 TEST_F(TPMAutoUpdateModePolicyHandlerTest,
182 ShowUpdateOnRebootNotificationNoTimer) {
183 TPMAutoUpdateModePolicyHandler tpm_update_policy_handler(
184 chromeos::CrosSettings::Get(), local_state_.Get());
185 tpm_update_policy_handler.SetUpdateCheckerCallbackForTesting(
186 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::CheckForUpdate,
187 weak_factory_.GetWeakPtr()));
188 tpm_update_policy_handler.SetShowNotificationCallbackForTesting(
189 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::ShowNotification,
190 base::Unretained(this)));
191
192 const AccountId account_id(
193 AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId));
194 user_manager_->AddUser(account_id);
195 user_manager_->LoginUser(account_id);
196
197 update_available_ = true;
198
199 // First notification was shwed more than 24 hours ago.
200 base::Time yesterday = base::Time::Now() - base::TimeDelta::FromHours(25);
201 local_state_.Get()->SetInt64(
202 prefs::kTPMUpdatePlannedNotificationShownTime,
203 yesterday.ToDeltaSinceWindowsEpoch().InSeconds());
204
205 SetAutoUpdateMode(AutoUpdateMode::kUserAcknowledgment);
206 base::RunLoop().RunUntilIdle();
207
208 // TPM update is not triggered.
209 EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
210 ->start_tpm_firmware_update_call_count());
211
212 // Show planned update notification.
213 EXPECT_EQ(last_shown_notification_,
214 chromeos::TpmAutoUpdateUserNotification::kOnNextReboot);
215 }
216
217 // Verify that the notification informing the user that an update will happen at
218 // the next reboot is triggered by the timer.
TEST_F(TPMAutoUpdateModePolicyHandlerTest,ShowUpdateOnRebootNotificationTimer)219 TEST_F(TPMAutoUpdateModePolicyHandlerTest,
220 ShowUpdateOnRebootNotificationTimer) {
221 TPMAutoUpdateModePolicyHandler tpm_update_policy_handler(
222 chromeos::CrosSettings::Get(), local_state_.Get());
223 tpm_update_policy_handler.SetUpdateCheckerCallbackForTesting(
224 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::CheckForUpdate,
225 weak_factory_.GetWeakPtr()));
226 tpm_update_policy_handler.SetShowNotificationCallbackForTesting(
227 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::ShowNotification,
228 base::Unretained(this)));
229
230 auto mock_timer = std::make_unique<base::MockOneShotTimer>();
231 auto* mock_timer_ptr = mock_timer.get();
232
233 tpm_update_policy_handler.SetNotificationTimerForTesting(
234 std::move(mock_timer));
235
236 const AccountId account_id(
237 AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId));
238 user_manager_->AddUser(account_id);
239 user_manager_->LoginUser(account_id);
240
241 update_available_ = true;
242
243 SetAutoUpdateMode(AutoUpdateMode::kUserAcknowledgment);
244 base::RunLoop().RunUntilIdle();
245 EXPECT_EQ(0, chromeos::FakeSessionManagerClient::Get()
246 ->start_tpm_firmware_update_call_count());
247
248 // Show planned update notification.
249 EXPECT_EQ(last_shown_notification_,
250 chromeos::TpmAutoUpdateUserNotification::kPlanned);
251
252 mock_timer_ptr->Fire();
253
254 // Show update at reboot notification.
255 EXPECT_EQ(last_shown_notification_,
256 chromeos::TpmAutoUpdateUserNotification::kOnNextReboot);
257 }
258
259 // TPM update with user acknowlegment triggered.
TEST_F(TPMAutoUpdateModePolicyHandlerTest,UpdateWithUserAcknowlegment)260 TEST_F(TPMAutoUpdateModePolicyHandlerTest, UpdateWithUserAcknowlegment) {
261 TPMAutoUpdateModePolicyHandler tpm_update_policy_handler(
262 chromeos::CrosSettings::Get(), local_state_.Get());
263 tpm_update_policy_handler.SetUpdateCheckerCallbackForTesting(
264 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::CheckForUpdate,
265 weak_factory_.GetWeakPtr()));
266 tpm_update_policy_handler.SetShowNotificationCallbackForTesting(
267 base::BindRepeating(&TPMAutoUpdateModePolicyHandlerTest::ShowNotification,
268 base::Unretained(this)));
269
270 update_available_ = true;
271
272 // Update at next reboot notification already shown.
273 local_state_.Get()->SetBoolean(prefs::kTPMUpdateOnNextRebootNotificationShown,
274 true);
275 SetAutoUpdateMode(AutoUpdateMode::kUserAcknowledgment);
276 base::RunLoop().RunUntilIdle();
277
278 // Update is triggered.
279 EXPECT_EQ(1, chromeos::FakeSessionManagerClient::Get()
280 ->start_tpm_firmware_update_call_count());
281 }
282
283 } // namespace policy
284