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