1 // Copyright 2018 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 "ash/detachable_base/detachable_base_handler.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "ash/detachable_base/detachable_base_observer.h"
11 #include "ash/detachable_base/detachable_base_pairing_status.h"
12 #include "ash/public/cpp/session/user_info.h"
13 #include "base/macros.h"
14 #include "base/run_loop.h"
15 #include "base/test/task_environment.h"
16 #include "base/time/time.h"
17 #include "chromeos/dbus/hammerd/fake_hammerd_client.h"
18 #include "chromeos/dbus/power/fake_power_manager_client.h"
19 #include "components/account_id/account_id.h"
20 #include "components/prefs/testing_pref_service.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace ash {
24
25 namespace {
26
27 enum class UserType {
28 kNormal,
29 kEphemeral,
30 };
31
CreateUser(const std::string & email,const std::string & gaia_id,UserType user_type)32 UserInfo CreateUser(const std::string& email,
33 const std::string& gaia_id,
34 UserType user_type) {
35 UserInfo user;
36 user.account_id = AccountId::FromUserEmailGaiaId(email, gaia_id);
37 user.is_ephemeral = user_type == UserType::kEphemeral;
38 return user;
39 }
40
41 class TestBaseObserver : public DetachableBaseObserver {
42 public:
43 TestBaseObserver() = default;
44 ~TestBaseObserver() override = default;
45
pairing_status_changed_count() const46 int pairing_status_changed_count() const {
47 return pairing_status_changed_count_;
48 }
49
reset_pairing_status_changed_count()50 void reset_pairing_status_changed_count() {
51 pairing_status_changed_count_ = 0;
52 }
53
update_required_changed_count() const54 int update_required_changed_count() const {
55 return update_required_changed_count_;
56 }
57
requires_update() const58 bool requires_update() const { return requires_update_; }
59
60 // DetachableBaseObserver:
OnDetachableBasePairingStatusChanged(DetachableBasePairingStatus status)61 void OnDetachableBasePairingStatusChanged(
62 DetachableBasePairingStatus status) override {
63 pairing_status_changed_count_++;
64 }
65
OnDetachableBaseRequiresUpdateChanged(bool requires_update)66 void OnDetachableBaseRequiresUpdateChanged(bool requires_update) override {
67 update_required_changed_count_++;
68 requires_update_ = requires_update;
69 }
70
71 private:
72 int pairing_status_changed_count_ = 0;
73 int update_required_changed_count_ = 0;
74 bool requires_update_ = false;
75
76 DISALLOW_COPY_AND_ASSIGN(TestBaseObserver);
77 };
78
79 } // namespace
80
81 class DetachableBaseHandlerTest : public testing::Test {
82 public:
83 DetachableBaseHandlerTest() = default;
84 ~DetachableBaseHandlerTest() override = default;
85
86 // testing::Test:
SetUp()87 void SetUp() override {
88 chromeos::HammerdClient::InitializeFake();
89 hammerd_client_ = chromeos::FakeHammerdClient::Get();
90
91 chromeos::PowerManagerClient::InitializeFake();
92 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
93 chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks());
94
95 default_user_ = CreateUser("user_1@foo.bar", "111111", UserType::kNormal);
96
97 DetachableBaseHandler::RegisterPrefs(local_state_.registry());
98 handler_ = std::make_unique<DetachableBaseHandler>(&local_state_);
99 handler_->AddObserver(&detachable_base_observer_);
100 }
101
TearDown()102 void TearDown() override {
103 handler_->RemoveObserver(&detachable_base_observer_);
104 handler_.reset();
105 hammerd_client_ = nullptr;
106 chromeos::PowerManagerClient::Shutdown();
107 chromeos::HammerdClient::Shutdown();
108 }
109
110 protected:
111 // Simulates system events associated with the detachable base being switched.
ChangePairedBase(const std::vector<uint8_t> & base_id)112 void ChangePairedBase(const std::vector<uint8_t>& base_id) {
113 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
114 chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
115 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
116 chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks());
117 detachable_base_observer_.reset_pairing_status_changed_count();
118
119 hammerd_client_->FirePairChallengeSucceededSignal(base_id);
120 }
121
RestartHandler()122 void RestartHandler() {
123 handler_->RemoveObserver(&detachable_base_observer_);
124 handler_ = std::make_unique<DetachableBaseHandler>(&local_state_);
125 handler_->AddObserver(&detachable_base_observer_);
126 }
127
128 chromeos::FakeHammerdClient* hammerd_client_ = nullptr;
129
130 TestBaseObserver detachable_base_observer_;
131
132 std::unique_ptr<DetachableBaseHandler> handler_;
133
134 UserInfo default_user_;
135
136 private:
137 base::test::TaskEnvironment task_environment_;
138
139 TestingPrefServiceSimple local_state_;
140
141 DISALLOW_COPY_AND_ASSIGN(DetachableBaseHandlerTest);
142 };
143
TEST_F(DetachableBaseHandlerTest,NoDetachableBase)144 TEST_F(DetachableBaseHandlerTest, NoDetachableBase) {
145 // Run loop so the handler picks up initial power manager state.
146 base::RunLoop().RunUntilIdle();
147
148 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
149 EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
150 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
151 }
152
TEST_F(DetachableBaseHandlerTest,TabletModeOnOnStartup)153 TEST_F(DetachableBaseHandlerTest, TabletModeOnOnStartup) {
154 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
155 chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
156 RestartHandler();
157
158 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
159 chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks());
160 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
161
162 // Run loop so the handler picks up initial power manager state.
163 base::RunLoop().RunUntilIdle();
164
165 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
166 handler_->GetPairingStatus());
167 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
168 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
169 }
170
TEST_F(DetachableBaseHandlerTest,SuccessfullPairing)171 TEST_F(DetachableBaseHandlerTest, SuccessfullPairing) {
172 // Run loop so the handler picks up initial power manager state.
173 base::RunLoop().RunUntilIdle();
174
175 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
176 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
177
178 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
179 handler_->GetPairingStatus());
180 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
181 // The user should not be notified when they attach a base for the first time,
182 // so the first paired base should be reported as kAuthenticated rather than
183 // kAuthenticatedNotMatchingLastUsed.
184 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
185 detachable_base_observer_.reset_pairing_status_changed_count();
186
187 // Assume the base has been detached when the device switches to tablet mode.
188 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
189 chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
190 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
191 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
192 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
193 detachable_base_observer_.reset_pairing_status_changed_count();
194
195 // When the device exits tablet mode again, the base should not be reported
196 // as paired until it's finished pairing.
197 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
198 chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks());
199 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
200 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
201
202 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
203 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
204 handler_->GetPairingStatus());
205 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
206 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
207 detachable_base_observer_.reset_pairing_status_changed_count();
208 }
209
TEST_F(DetachableBaseHandlerTest,DetachableBasePairingFailure)210 TEST_F(DetachableBaseHandlerTest, DetachableBasePairingFailure) {
211 // Run loop so the handler picks up initial power manager state.
212 base::RunLoop().RunUntilIdle();
213
214 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
215 hammerd_client_->FirePairChallengeFailedSignal();
216
217 EXPECT_EQ(DetachableBasePairingStatus::kNotAuthenticated,
218 handler_->GetPairingStatus());
219 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
220 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
221 detachable_base_observer_.reset_pairing_status_changed_count();
222
223 // Assume the base has been detached when the device switches to tablet mode.
224 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
225 chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
226 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
227 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
228 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
229 detachable_base_observer_.reset_pairing_status_changed_count();
230 }
231
TEST_F(DetachableBaseHandlerTest,InvalidDetachableBase)232 TEST_F(DetachableBaseHandlerTest, InvalidDetachableBase) {
233 // Run loop so the handler picks up initial power manager state.
234 base::RunLoop().RunUntilIdle();
235
236 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
237 hammerd_client_->FireInvalidBaseConnectedSignal();
238
239 EXPECT_EQ(DetachableBasePairingStatus::kInvalidDevice,
240 handler_->GetPairingStatus());
241 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
242 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
243 detachable_base_observer_.reset_pairing_status_changed_count();
244
245 // Assume the base has been detached when the device switches to tablet mode.
246 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
247 chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
248 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
249 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
250 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
251 detachable_base_observer_.reset_pairing_status_changed_count();
252 }
253
TEST_F(DetachableBaseHandlerTest,PairingSuccessDuringInit)254 TEST_F(DetachableBaseHandlerTest, PairingSuccessDuringInit) {
255 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
256
257 // DetachableBaseHandler updates base pairing state only after it confirms the
258 // device is not in tablet mode.
259 EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
260 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
261 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
262
263 // Run loop so the callback for getting the initial power manager state gets
264 // run.
265 base::RunLoop().RunUntilIdle();
266
267 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
268 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
269 handler_->GetPairingStatus());
270 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
271 detachable_base_observer_.reset_pairing_status_changed_count();
272 }
273
TEST_F(DetachableBaseHandlerTest,PairingFailDuringInit)274 TEST_F(DetachableBaseHandlerTest, PairingFailDuringInit) {
275 hammerd_client_->FirePairChallengeFailedSignal();
276
277 // DetachableBaseHandler updates base pairing state only after it confirms the
278 // device is not in tablet mode.
279 EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
280 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
281 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
282
283 // Run loop so the callback for getting the initial power manager state gets
284 // run.
285 base::RunLoop().RunUntilIdle();
286
287 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
288 EXPECT_EQ(DetachableBasePairingStatus::kNotAuthenticated,
289 handler_->GetPairingStatus());
290 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
291 detachable_base_observer_.reset_pairing_status_changed_count();
292 }
293
TEST_F(DetachableBaseHandlerTest,InvalidDeviceDuringInit)294 TEST_F(DetachableBaseHandlerTest, InvalidDeviceDuringInit) {
295 hammerd_client_->FireInvalidBaseConnectedSignal();
296
297 // DetachableBaseHandler updates base pairing state only after it confirms the
298 // device is not in tablet mode.
299 EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
300 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
301 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
302
303 // Run loop so the callback for getting the initial power manager state gets
304 // run.
305 base::RunLoop().RunUntilIdle();
306
307 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
308 EXPECT_EQ(DetachableBasePairingStatus::kInvalidDevice,
309 handler_->GetPairingStatus());
310 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
311 detachable_base_observer_.reset_pairing_status_changed_count();
312 }
313
TEST_F(DetachableBaseHandlerTest,TabletModeTurnedOnDuringHandlerInit)314 TEST_F(DetachableBaseHandlerTest, TabletModeTurnedOnDuringHandlerInit) {
315 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
316 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
317 chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
318
319 // Run loop so the callback for getting the initial power manager state gets
320 // run.
321 base::RunLoop().RunUntilIdle();
322
323 EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
324 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
325 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
326 }
327
TEST_F(DetachableBaseHandlerTest,DetachableBaseChangeDetection)328 TEST_F(DetachableBaseHandlerTest, DetachableBaseChangeDetection) {
329 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
330 chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks());
331 // Run loop so the callback for getting the initial power manager state gets
332 // run.
333 base::RunLoop().RunUntilIdle();
334 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
335
336 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
337 handler_->GetPairingStatus());
338 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
339 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
340 detachable_base_observer_.reset_pairing_status_changed_count();
341
342 // Set the current base as last used by the user.
343 handler_->SetPairedBaseAsLastUsedByUser(default_user_);
344
345 // Simulate the paired base change.
346 ChangePairedBase({0x04, 0x05, 0x06, 0x07});
347
348 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
349 handler_->GetPairingStatus());
350 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
351 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
352 detachable_base_observer_.reset_pairing_status_changed_count();
353
354 // Switch back to last used base.
355 ChangePairedBase({0x01, 0x02, 0x03, 0x04});
356
357 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
358 handler_->GetPairingStatus());
359 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
360 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
361 detachable_base_observer_.reset_pairing_status_changed_count();
362
363 // The last used base should be preserved if the detachable base handler is
364 // restarted after the last used base was set.
365 RestartHandler();
366 base::RunLoop().RunUntilIdle();
367
368 hammerd_client_->FirePairChallengeSucceededSignal({0x04, 0x05, 0x06, 0x07});
369
370 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
371 handler_->GetPairingStatus());
372 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
373 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
374 detachable_base_observer_.reset_pairing_status_changed_count();
375 }
376
TEST_F(DetachableBaseHandlerTest,MultiUser)377 TEST_F(DetachableBaseHandlerTest, MultiUser) {
378 // Assume the user_1 has a last used base.
379 base::RunLoop().RunUntilIdle();
380 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
381 handler_->SetPairedBaseAsLastUsedByUser(default_user_);
382 detachable_base_observer_.reset_pairing_status_changed_count();
383
384 // Restart the handler, so it's initialized with the previously set up prefs
385 // state.
386 RestartHandler();
387 base::RunLoop().RunUntilIdle();
388
389 const UserInfo second_user =
390 CreateUser("user_2@foo.bar", "222222", UserType::kNormal);
391
392 EXPECT_EQ(DetachableBasePairingStatus::kNone, handler_->GetPairingStatus());
393 EXPECT_EQ(0, detachable_base_observer_.pairing_status_changed_count());
394 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
395 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
396
397 // Pair a detachable base different than the one used by user_1.
398 hammerd_client_->FirePairChallengeSucceededSignal({0x04, 0x05, 0x06, 0x07});
399
400 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
401 handler_->GetPairingStatus());
402 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
403 // The base for user_1 has changed.
404 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
405 // User 2 has not used a detachable base yet - the base should be reported as
406 // matching last used base.
407 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
408 detachable_base_observer_.reset_pairing_status_changed_count();
409
410 // Set the last used detachable base for user 2, and pair the initial base.
411 handler_->SetPairedBaseAsLastUsedByUser(second_user);
412
413 ChangePairedBase({0x01, 0x02, 0x03, 0x04});
414
415 // This time, the second user should be notified the base has been changed.
416 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
417 handler_->GetPairingStatus());
418 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
419 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
420 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
421 detachable_base_observer_.reset_pairing_status_changed_count();
422
423 // Set the base for user 2 to the current one.
424 handler_->SetPairedBaseAsLastUsedByUser(second_user);
425
426 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
427
428 // When the base is paired next time, it should be considered authenticated
429 // for both users.
430 ChangePairedBase({0x01, 0x02, 0x03, 0x04});
431
432 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
433 handler_->GetPairingStatus());
434 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
435 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
436 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
437 detachable_base_observer_.reset_pairing_status_changed_count();
438 }
439
TEST_F(DetachableBaseHandlerTest,SwitchToNonAuthenticatedBase)440 TEST_F(DetachableBaseHandlerTest, SwitchToNonAuthenticatedBase) {
441 // Run loop so the handler picks up initial power manager state.
442 base::RunLoop().RunUntilIdle();
443
444 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
445 handler_->SetPairedBaseAsLastUsedByUser(default_user_);
446 detachable_base_observer_.reset_pairing_status_changed_count();
447
448 // Switch to non-trusted base, and verify it's reported as such regardless
449 // of whether the user had previously used a detachable base.
450 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
451 chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
452 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
453 chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks());
454 detachable_base_observer_.reset_pairing_status_changed_count();
455
456 hammerd_client_->FirePairChallengeFailedSignal();
457
458 const UserInfo second_user =
459 CreateUser("user_2@foo.bar", "222222", UserType::kNormal);
460
461 EXPECT_EQ(DetachableBasePairingStatus::kNotAuthenticated,
462 handler_->GetPairingStatus());
463 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
464 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
465 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
466 detachable_base_observer_.reset_pairing_status_changed_count();
467 }
468
TEST_F(DetachableBaseHandlerTest,SwitchToInvalidBase)469 TEST_F(DetachableBaseHandlerTest, SwitchToInvalidBase) {
470 // Run loop so the handler picks up initial power manager state.
471 base::RunLoop().RunUntilIdle();
472
473 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
474 handler_->SetPairedBaseAsLastUsedByUser(default_user_);
475 detachable_base_observer_.reset_pairing_status_changed_count();
476
477 // Switch to an invalid base, and verify it's reported as such regardless
478 // of whether the user had previously used a base.
479 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
480 chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
481 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
482 chromeos::PowerManagerClient::TabletMode::OFF, base::TimeTicks());
483 detachable_base_observer_.reset_pairing_status_changed_count();
484
485 hammerd_client_->FireInvalidBaseConnectedSignal();
486
487 const UserInfo second_user =
488 CreateUser("user_2@foo.bar", "222222", UserType::kNormal);
489
490 EXPECT_EQ(DetachableBasePairingStatus::kInvalidDevice,
491 handler_->GetPairingStatus());
492 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
493 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
494 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
495 detachable_base_observer_.reset_pairing_status_changed_count();
496 }
497
TEST_F(DetachableBaseHandlerTest,RemoveUserData)498 TEST_F(DetachableBaseHandlerTest, RemoveUserData) {
499 const UserInfo second_user =
500 CreateUser("user_2@foo.bar", "222222", UserType::kNormal);
501
502 // Assume the user_1 has a last used base.
503 base::RunLoop().RunUntilIdle();
504 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
505 handler_->SetPairedBaseAsLastUsedByUser(default_user_);
506 handler_->SetPairedBaseAsLastUsedByUser(second_user);
507 detachable_base_observer_.reset_pairing_status_changed_count();
508
509 ChangePairedBase({0x04, 0x05, 0x06});
510
511 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
512 handler_->GetPairingStatus());
513 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
514 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
515 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
516 detachable_base_observer_.reset_pairing_status_changed_count();
517
518 // Remove the data for user_2, and verify that the paired base is reported
519 // as authenticated when the paired base changes again.
520 handler_->RemoveUserData(second_user);
521 ChangePairedBase({0x07, 0x08, 0x09});
522
523 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
524 handler_->GetPairingStatus());
525 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
526 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
527 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
528 detachable_base_observer_.reset_pairing_status_changed_count();
529
530 // Verify that paired base will be properly set again for the previously
531 // removed user.
532 handler_->SetPairedBaseAsLastUsedByUser(second_user);
533 ChangePairedBase({0x01, 0x02, 0x03, 0x04});
534
535 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
536 handler_->GetPairingStatus());
537 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
538 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(default_user_));
539 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(second_user));
540 detachable_base_observer_.reset_pairing_status_changed_count();
541 }
542
TEST_F(DetachableBaseHandlerTest,EphemeralUser)543 TEST_F(DetachableBaseHandlerTest, EphemeralUser) {
544 base::RunLoop().RunUntilIdle();
545
546 const UserInfo ephemeral_user =
547 CreateUser("user_3@foo.bar", "333333", UserType::kEphemeral);
548 hammerd_client_->FirePairChallengeSucceededSignal({0x01, 0x02, 0x03, 0x04});
549 handler_->SetPairedBaseAsLastUsedByUser(ephemeral_user);
550 detachable_base_observer_.reset_pairing_status_changed_count();
551
552 ChangePairedBase({0x04, 0x05, 0x06});
553
554 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
555 handler_->GetPairingStatus());
556 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
557 EXPECT_FALSE(handler_->PairedBaseMatchesLastUsedByUser(ephemeral_user));
558 detachable_base_observer_.reset_pairing_status_changed_count();
559
560 ChangePairedBase({0x01, 0x02, 0x03, 0x04});
561
562 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
563 handler_->GetPairingStatus());
564 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
565 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(ephemeral_user));
566 detachable_base_observer_.reset_pairing_status_changed_count();
567
568 // Verify that the information about the last used base gets lost if the
569 // detachable base handler is reset (given that the info was saved for an
570 // ephemeral user).
571 RestartHandler();
572 base::RunLoop().RunUntilIdle();
573 hammerd_client_->FirePairChallengeSucceededSignal({0x04, 0x05, 0x06, 0x07});
574
575 EXPECT_EQ(DetachableBasePairingStatus::kAuthenticated,
576 handler_->GetPairingStatus());
577 EXPECT_EQ(1, detachable_base_observer_.pairing_status_changed_count());
578 EXPECT_TRUE(handler_->PairedBaseMatchesLastUsedByUser(ephemeral_user));
579 detachable_base_observer_.reset_pairing_status_changed_count();
580 }
581
TEST_F(DetachableBaseHandlerTest,NotifyObserversWhenBaseUpdateRequired)582 TEST_F(DetachableBaseHandlerTest, NotifyObserversWhenBaseUpdateRequired) {
583 hammerd_client_->FireBaseFirmwareNeedUpdateSignal();
584 EXPECT_EQ(1, detachable_base_observer_.update_required_changed_count());
585 EXPECT_TRUE(detachable_base_observer_.requires_update());
586
587 hammerd_client_->FireBaseFirmwareUpdateSucceededSignal();
588 EXPECT_EQ(2, detachable_base_observer_.update_required_changed_count());
589 EXPECT_FALSE(detachable_base_observer_.requires_update());
590 }
591
TEST_F(DetachableBaseHandlerTest,NotifyNoUpdateRequiredOnBaseDetach)592 TEST_F(DetachableBaseHandlerTest, NotifyNoUpdateRequiredOnBaseDetach) {
593 hammerd_client_->FireBaseFirmwareNeedUpdateSignal();
594 EXPECT_EQ(1, detachable_base_observer_.update_required_changed_count());
595 EXPECT_TRUE(detachable_base_observer_.requires_update());
596
597 chromeos::FakePowerManagerClient::Get()->SetTabletMode(
598 chromeos::PowerManagerClient::TabletMode::ON, base::TimeTicks());
599 EXPECT_EQ(2, detachable_base_observer_.update_required_changed_count());
600 EXPECT_FALSE(detachable_base_observer_.requires_update());
601 }
602
603 } // namespace ash
604