1 // Copyright 2014 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 "chromeos/components/proximity_auth/proximity_auth_system.h"
6
7 #include "chromeos/components/multidevice/logging/logging.h"
8 #include "chromeos/components/proximity_auth/proximity_auth_client.h"
9 #include "chromeos/components/proximity_auth/remote_device_life_cycle_impl.h"
10 #include "chromeos/components/proximity_auth/unlock_manager_impl.h"
11 #include "chromeos/services/secure_channel/public/cpp/client/secure_channel_client.h"
12
13 namespace proximity_auth {
14
ProximityAuthSystem(ScreenlockType screenlock_type,ProximityAuthClient * proximity_auth_client,chromeos::secure_channel::SecureChannelClient * secure_channel_client)15 ProximityAuthSystem::ProximityAuthSystem(
16 ScreenlockType screenlock_type,
17 ProximityAuthClient* proximity_auth_client,
18 chromeos::secure_channel::SecureChannelClient* secure_channel_client)
19 : secure_channel_client_(secure_channel_client),
20 unlock_manager_(
21 std::make_unique<UnlockManagerImpl>(screenlock_type,
22 proximity_auth_client)),
23 suspended_(false),
24 started_(false) {}
25
ProximityAuthSystem(chromeos::secure_channel::SecureChannelClient * secure_channel_client,std::unique_ptr<UnlockManager> unlock_manager)26 ProximityAuthSystem::ProximityAuthSystem(
27 chromeos::secure_channel::SecureChannelClient* secure_channel_client,
28 std::unique_ptr<UnlockManager> unlock_manager)
29 : secure_channel_client_(secure_channel_client),
30 unlock_manager_(std::move(unlock_manager)),
31 suspended_(false),
32 started_(false) {}
33
~ProximityAuthSystem()34 ProximityAuthSystem::~ProximityAuthSystem() {
35 ScreenlockBridge::Get()->RemoveObserver(this);
36 unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
37 }
38
Start()39 void ProximityAuthSystem::Start() {
40 if (started_)
41 return;
42 started_ = true;
43 ScreenlockBridge::Get()->AddObserver(this);
44 const AccountId& focused_account_id =
45 ScreenlockBridge::Get()->focused_account_id();
46 if (focused_account_id.is_valid())
47 OnFocusedUserChanged(focused_account_id);
48 }
49
Stop()50 void ProximityAuthSystem::Stop() {
51 if (!started_)
52 return;
53 started_ = false;
54 ScreenlockBridge::Get()->RemoveObserver(this);
55 OnFocusedUserChanged(EmptyAccountId());
56 }
57
SetRemoteDevicesForUser(const AccountId & account_id,const chromeos::multidevice::RemoteDeviceRefList & remote_devices,base::Optional<chromeos::multidevice::RemoteDeviceRef> local_device)58 void ProximityAuthSystem::SetRemoteDevicesForUser(
59 const AccountId& account_id,
60 const chromeos::multidevice::RemoteDeviceRefList& remote_devices,
61 base::Optional<chromeos::multidevice::RemoteDeviceRef> local_device) {
62 PA_LOG(VERBOSE) << "Setting devices for user " << account_id.Serialize()
63 << ". Remote device count: " << remote_devices.size()
64 << ", Local device: ["
65 << (local_device.has_value() ? "present" : "absent") << "].";
66
67 remote_devices_map_[account_id] = remote_devices;
68 local_device_map_.emplace(account_id, *local_device);
69
70 if (started_) {
71 const AccountId& focused_account_id =
72 ScreenlockBridge::Get()->focused_account_id();
73 if (focused_account_id.is_valid())
74 OnFocusedUserChanged(focused_account_id);
75 }
76 }
77
78 chromeos::multidevice::RemoteDeviceRefList
GetRemoteDevicesForUser(const AccountId & account_id) const79 ProximityAuthSystem::GetRemoteDevicesForUser(
80 const AccountId& account_id) const {
81 if (remote_devices_map_.find(account_id) == remote_devices_map_.end())
82 return chromeos::multidevice::RemoteDeviceRefList();
83 return remote_devices_map_.at(account_id);
84 }
85
OnAuthAttempted()86 void ProximityAuthSystem::OnAuthAttempted() {
87 unlock_manager_->OnAuthAttempted(mojom::AuthType::USER_CLICK);
88 }
89
OnSuspend()90 void ProximityAuthSystem::OnSuspend() {
91 PA_LOG(INFO) << "Preparing for device suspension.";
92 DCHECK(!suspended_);
93 suspended_ = true;
94 unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
95 remote_device_life_cycle_.reset();
96 }
97
OnSuspendDone()98 void ProximityAuthSystem::OnSuspendDone() {
99 PA_LOG(INFO) << "Device resumed from suspension.";
100 DCHECK(suspended_);
101 suspended_ = false;
102
103 if (!ScreenlockBridge::Get()->IsLocked()) {
104 PA_LOG(INFO) << "Suspend done, but no lock screen.";
105 } else if (!started_) {
106 PA_LOG(INFO) << "Suspend done, but not system started.";
107 } else {
108 OnFocusedUserChanged(ScreenlockBridge::Get()->focused_account_id());
109 }
110 }
111
CancelConnectionAttempt()112 void ProximityAuthSystem::CancelConnectionAttempt() {
113 unlock_manager_->CancelConnectionAttempt();
114 }
115
116 std::unique_ptr<RemoteDeviceLifeCycle>
CreateRemoteDeviceLifeCycle(chromeos::multidevice::RemoteDeviceRef remote_device,base::Optional<chromeos::multidevice::RemoteDeviceRef> local_device)117 ProximityAuthSystem::CreateRemoteDeviceLifeCycle(
118 chromeos::multidevice::RemoteDeviceRef remote_device,
119 base::Optional<chromeos::multidevice::RemoteDeviceRef> local_device) {
120 return std::make_unique<RemoteDeviceLifeCycleImpl>(
121 remote_device, local_device, secure_channel_client_);
122 }
123
OnScreenDidLock(ScreenlockBridge::LockHandler::ScreenType screen_type)124 void ProximityAuthSystem::OnScreenDidLock(
125 ScreenlockBridge::LockHandler::ScreenType screen_type) {
126 const AccountId& focused_account_id =
127 ScreenlockBridge::Get()->focused_account_id();
128 if (focused_account_id.is_valid())
129 OnFocusedUserChanged(focused_account_id);
130 }
131
OnScreenDidUnlock(ScreenlockBridge::LockHandler::ScreenType screen_type)132 void ProximityAuthSystem::OnScreenDidUnlock(
133 ScreenlockBridge::LockHandler::ScreenType screen_type) {
134 unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
135 remote_device_life_cycle_.reset();
136 }
137
OnFocusedUserChanged(const AccountId & account_id)138 void ProximityAuthSystem::OnFocusedUserChanged(const AccountId& account_id) {
139 // Update the current RemoteDeviceLifeCycle to the focused user.
140 if (remote_device_life_cycle_) {
141 if (remote_device_life_cycle_->GetRemoteDevice().user_email() !=
142 account_id.GetUserEmail()) {
143 PA_LOG(INFO) << "Focused user changed, destroying life cycle for "
144 << account_id.Serialize() << ".";
145 unlock_manager_->SetRemoteDeviceLifeCycle(nullptr);
146 remote_device_life_cycle_.reset();
147 } else {
148 PA_LOG(INFO) << "Refocused on a user who is already focused.";
149 return;
150 }
151 }
152
153 if (remote_devices_map_.find(account_id) == remote_devices_map_.end() ||
154 remote_devices_map_[account_id].size() == 0) {
155 PA_LOG(INFO) << "User " << account_id.Serialize()
156 << " does not have a Smart Lock host device.";
157 return;
158 }
159 if (local_device_map_.find(account_id) == local_device_map_.end()) {
160 PA_LOG(INFO) << "User " << account_id.Serialize()
161 << " does not have a local device.";
162 return;
163 }
164
165 // TODO(tengs): We currently assume each user has only one RemoteDevice, so we
166 // can simply take the first item in the list.
167 chromeos::multidevice::RemoteDeviceRef remote_device =
168 remote_devices_map_[account_id][0];
169
170 base::Optional<chromeos::multidevice::RemoteDeviceRef> local_device;
171 local_device = local_device_map_.at(account_id);
172
173 if (!suspended_) {
174 PA_LOG(INFO) << "Creating RemoteDeviceLifeCycle for focused user: "
175 << account_id.Serialize();
176 remote_device_life_cycle_ =
177 CreateRemoteDeviceLifeCycle(remote_device, local_device);
178
179 // UnlockManager listens for Bluetooth power change events, and is therefore
180 // responsible for starting RemoteDeviceLifeCycle when Bluetooth becomes
181 // powered.
182 unlock_manager_->SetRemoteDeviceLifeCycle(remote_device_life_cycle_.get());
183 }
184 }
185
186 } // namespace proximity_auth
187