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.
5 #include "chrome/browser/signin/easy_unlock_service.h"
7 #include "apps/app_lifetime_monitor.h"
8 #include "apps/app_lifetime_monitor_factory.h"
10 #include "base/command_line.h"
11 #include "base/guid.h"
12 #include "base/logging.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/prefs/pref_registry_simple.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/prefs/scoped_user_pref_update.h"
17 #include "base/sys_info.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "base/time/time.h"
20 #include "base/values.h"
21 #include "base/version.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/signin/chrome_proximity_auth_client.h"
25 #include "chrome/browser/signin/easy_unlock_app_manager.h"
26 #include "chrome/browser/signin/easy_unlock_service_factory.h"
27 #include "chrome/browser/signin/easy_unlock_service_observer.h"
28 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
29 #include "chrome/browser/signin/signin_manager_factory.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/extensions/extension_constants.h"
32 #include "chrome/common/pref_names.h"
33 #include "components/pref_registry/pref_registry_syncable.h"
34 #include "components/proximity_auth/ble/proximity_auth_ble_system.h"
35 #include "components/proximity_auth/cryptauth/cryptauth_client_impl.h"
36 #include "components/proximity_auth/cryptauth/cryptauth_device_manager.h"
37 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h"
38 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
39 #include "components/proximity_auth/screenlock_bridge.h"
40 #include "components/proximity_auth/switches.h"
41 #include "components/signin/core/browser/profile_oauth2_token_service.h"
42 #include "components/signin/core/browser/signin_manager.h"
43 #include "components/user_manager/user.h"
44 #include "components/version_info/version_info.h"
45 #include "device/bluetooth/bluetooth_adapter.h"
46 #include "device/bluetooth/bluetooth_adapter_factory.h"
48 #if defined(OS_CHROMEOS)
49 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
50 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
51 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
52 #include "chrome/browser/chromeos/login/easy_unlock/secure_message_delegate_chromeos.h"
53 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
54 #include "chrome/browser/chromeos/profiles/profile_helper.h"
55 #include "chromeos/dbus/dbus_thread_manager.h"
56 #include "chromeos/dbus/power_manager_client.h"
57 #include "components/user_manager/user_manager.h"
61 #include "base/win/windows_version.h"
64 using proximity_auth::ScreenlockState
;
71 BT_LOW_ENERGY_CAPABLE
,
75 PrefService
* GetLocalState() {
76 return g_browser_process
? g_browser_process
->local_state() : NULL
;
81 EasyUnlockService::UserSettings::UserSettings()
82 : require_close_proximity(false) {
85 EasyUnlockService::UserSettings::~UserSettings() {
89 EasyUnlockService
* EasyUnlockService::Get(Profile
* profile
) {
90 return EasyUnlockServiceFactory::GetForBrowserContext(profile
);
94 EasyUnlockService
* EasyUnlockService::GetForUser(
95 const user_manager::User
& user
) {
96 #if defined(OS_CHROMEOS)
97 Profile
* profile
= chromeos::ProfileHelper::Get()->GetProfileByUser(&user
);
100 return EasyUnlockService::Get(profile
);
106 class EasyUnlockService::BluetoothDetector
107 : public device::BluetoothAdapter::Observer
,
108 public apps::AppLifetimeMonitor::Observer
{
110 explicit BluetoothDetector(EasyUnlockService
* service
)
112 weak_ptr_factory_(this) {
113 apps::AppLifetimeMonitorFactory::GetForProfile(service_
->profile())
117 ~BluetoothDetector() override
{
119 adapter_
->RemoveObserver(this);
120 apps::AppLifetimeMonitorFactory::GetForProfile(service_
->profile())
121 ->RemoveObserver(this);
125 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
128 device::BluetoothAdapterFactory::GetAdapter(
129 base::Bind(&BluetoothDetector::OnAdapterInitialized
,
130 weak_ptr_factory_
.GetWeakPtr()));
133 bool IsPresent() const { return adapter_
.get() && adapter_
->IsPresent(); }
135 // device::BluetoothAdapter::Observer:
136 void AdapterPresentChanged(device::BluetoothAdapter
* adapter
,
137 bool present
) override
{
138 service_
->OnBluetoothAdapterPresentChanged();
141 device::BluetoothAdapter
* getAdapter() {
142 return adapter_
.get();
146 void OnAdapterInitialized(scoped_refptr
<device::BluetoothAdapter
> adapter
) {
148 adapter_
->AddObserver(this);
149 service_
->OnBluetoothAdapterPresentChanged();
151 #if !defined(OS_CHROMEOS)
152 // Bluetooth detection causes serious performance degradations on Mac
153 // and possibly other platforms as well: http://crbug.com/467316
154 // Since this feature is currently only offered for ChromeOS we just
155 // turn it off on other platforms once the inforamtion about the
156 // adapter has been gathered and reported.
157 // TODO(bcwhite,xiyuan): Revisit when non-chromeos platforms are supported.
158 adapter_
->RemoveObserver(this);
161 // TODO(tengs): At the moment, there is no way for Bluetooth discoverability
162 // to be turned on except through the Easy Unlock setup. If we step on any
163 // toes in the future then we need to revisit this guard.
164 if (adapter_
->IsDiscoverable())
165 TurnOffBluetoothDiscoverability();
166 #endif // !defined(OS_CHROMEOS)
169 // apps::AppLifetimeMonitor::Observer:
170 void OnAppDeactivated(Profile
* profile
, const std::string
& app_id
) override
{
171 // TODO(tengs): Refactor the lifetime management to EasyUnlockAppManager.
172 if (app_id
== extension_misc::kEasyUnlockAppId
)
173 TurnOffBluetoothDiscoverability();
176 void OnAppStop(Profile
* profile
, const std::string
& app_id
) override
{
177 // TODO(tengs): Refactor the lifetime management to EasyUnlockAppManager.
178 if (app_id
== extension_misc::kEasyUnlockAppId
)
179 TurnOffBluetoothDiscoverability();
182 void TurnOffBluetoothDiscoverability() {
184 adapter_
->SetDiscoverable(
185 false, base::Bind(&base::DoNothing
), base::Bind(&base::DoNothing
));
189 // Owner of this class and should out-live this class.
190 EasyUnlockService
* service_
;
191 scoped_refptr
<device::BluetoothAdapter
> adapter_
;
192 base::WeakPtrFactory
<BluetoothDetector
> weak_ptr_factory_
;
194 DISALLOW_COPY_AND_ASSIGN(BluetoothDetector
);
197 #if defined(OS_CHROMEOS)
198 class EasyUnlockService::PowerMonitor
199 : public chromeos::PowerManagerClient::Observer
{
201 explicit PowerMonitor(EasyUnlockService
* service
)
204 weak_ptr_factory_(this) {
205 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
209 ~PowerMonitor() override
{
210 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
211 RemoveObserver(this);
214 // Called when the remote device has been authenticated to record the time
215 // delta from waking up. No time will be recorded if the start-up time has
216 // already been recorded or if the system never went to sleep previously.
217 void RecordStartUpTime() {
218 if (wake_up_time_
.is_null())
220 UMA_HISTOGRAM_MEDIUM_TIMES(
221 "EasyUnlock.StartupTimeFromSuspend",
222 base::Time::Now() - wake_up_time_
);
223 wake_up_time_
= base::Time();
226 bool waking_up() const { return waking_up_
; }
229 // chromeos::PowerManagerClient::Observer:
230 void SuspendImminent() override
{ service_
->PrepareForSuspend(); }
232 void SuspendDone(const base::TimeDelta
& sleep_duration
) override
{
234 wake_up_time_
= base::Time::Now();
235 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
237 base::Bind(&PowerMonitor::ResetWakingUp
,
238 weak_ptr_factory_
.GetWeakPtr()),
239 base::TimeDelta::FromSeconds(5));
240 service_
->OnSuspendDone();
241 service_
->UpdateAppState();
242 // Note that |this| may get deleted after |UpdateAppState| is called.
245 void ResetWakingUp() {
247 service_
->UpdateAppState();
250 EasyUnlockService
* service_
;
252 base::Time wake_up_time_
;
253 base::WeakPtrFactory
<PowerMonitor
> weak_ptr_factory_
;
255 DISALLOW_COPY_AND_ASSIGN(PowerMonitor
);
259 EasyUnlockService::EasyUnlockService(Profile
* profile
)
261 proximity_auth_client_(profile
),
262 bluetooth_detector_(new BluetoothDetector(this)),
264 tpm_key_checked_(false),
265 weak_ptr_factory_(this) {
268 EasyUnlockService::~EasyUnlockService() {
272 void EasyUnlockService::RegisterProfilePrefs(
273 user_prefs::PrefRegistrySyncable
* registry
) {
274 registry
->RegisterBooleanPref(prefs::kEasyUnlockAllowed
, true);
275 registry
->RegisterBooleanPref(prefs::kEasyUnlockEnabled
, false);
276 registry
->RegisterDictionaryPref(prefs::kEasyUnlockPairing
,
277 new base::DictionaryValue());
278 registry
->RegisterBooleanPref(
279 prefs::kEasyUnlockProximityRequired
,
281 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
283 proximity_auth::CryptAuthGCMManager::RegisterPrefs(registry
);
284 proximity_auth::CryptAuthDeviceManager::RegisterPrefs(registry
);
285 proximity_auth::CryptAuthEnrollmentManager::RegisterPrefs(registry
);
287 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
288 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery
))
289 proximity_auth::ProximityAuthBleSystem::RegisterPrefs(registry
);
293 void EasyUnlockService::RegisterPrefs(PrefRegistrySimple
* registry
) {
294 registry
->RegisterStringPref(prefs::kEasyUnlockDeviceId
, std::string());
295 registry
->RegisterDictionaryPref(prefs::kEasyUnlockHardlockState
);
296 registry
->RegisterDictionaryPref(prefs::kEasyUnlockLocalStateUserPrefs
);
297 #if defined(OS_CHROMEOS)
298 EasyUnlockTpmKeyManager::RegisterLocalStatePrefs(registry
);
303 void EasyUnlockService::ResetLocalStateForUser(const std::string
& user_id
) {
304 DCHECK(!user_id
.empty());
306 PrefService
* local_state
= GetLocalState();
310 DictionaryPrefUpdate
update(local_state
, prefs::kEasyUnlockHardlockState
);
311 update
->RemoveWithoutPathExpansion(user_id
, NULL
);
313 #if defined(OS_CHROMEOS)
314 EasyUnlockTpmKeyManager::ResetLocalStateForUser(user_id
);
319 EasyUnlockService::UserSettings
EasyUnlockService::GetUserSettings(
320 const std::string
& user_id
) {
321 DCHECK(!user_id
.empty());
322 UserSettings user_settings
;
324 PrefService
* local_state
= GetLocalState();
326 return user_settings
;
328 const base::DictionaryValue
* all_user_prefs_dict
=
329 local_state
->GetDictionary(prefs::kEasyUnlockLocalStateUserPrefs
);
330 if (!all_user_prefs_dict
)
331 return user_settings
;
333 const base::DictionaryValue
* user_prefs_dict
;
334 if (!all_user_prefs_dict
->GetDictionaryWithoutPathExpansion(user_id
,
336 return user_settings
;
338 user_prefs_dict
->GetBooleanWithoutPathExpansion(
339 prefs::kEasyUnlockProximityRequired
,
340 &user_settings
.require_close_proximity
);
342 return user_settings
;
346 std::string
EasyUnlockService::GetDeviceId() {
347 PrefService
* local_state
= GetLocalState();
349 return std::string();
351 std::string device_id
= local_state
->GetString(prefs::kEasyUnlockDeviceId
);
352 if (device_id
.empty()) {
353 device_id
= base::GenerateGUID();
354 local_state
->SetString(prefs::kEasyUnlockDeviceId
, device_id
);
359 void EasyUnlockService::Initialize(
360 scoped_ptr
<EasyUnlockAppManager
> app_manager
) {
361 app_manager_
= app_manager
.Pass();
362 app_manager_
->EnsureReady(
363 base::Bind(&EasyUnlockService::InitializeOnAppManagerReady
,
364 weak_ptr_factory_
.GetWeakPtr()));
367 bool EasyUnlockService::IsAllowed() const {
371 if (!IsAllowedInternal())
374 #if defined(OS_CHROMEOS)
375 if (!bluetooth_detector_
->IsPresent())
380 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
385 bool EasyUnlockService::IsEnabled() const {
386 // The feature is enabled iff there are any paired devices.
387 const base::ListValue
* devices
= GetRemoteDevices();
388 return devices
&& !devices
->empty();
391 void EasyUnlockService::OpenSetupApp() {
392 app_manager_
->LaunchSetup();
395 void EasyUnlockService::SetHardlockState(
396 EasyUnlockScreenlockStateHandler::HardlockState state
) {
397 const std::string user_id
= GetUserEmail();
401 if (state
== GetHardlockState())
404 SetHardlockStateForUser(user_id
, state
);
407 EasyUnlockScreenlockStateHandler::HardlockState
408 EasyUnlockService::GetHardlockState() const {
409 EasyUnlockScreenlockStateHandler::HardlockState state
;
410 if (GetPersistedHardlockState(&state
))
413 return EasyUnlockScreenlockStateHandler::NO_HARDLOCK
;
416 bool EasyUnlockService::GetPersistedHardlockState(
417 EasyUnlockScreenlockStateHandler::HardlockState
* state
) const {
418 std::string user_id
= GetUserEmail();
422 PrefService
* local_state
= GetLocalState();
426 const base::DictionaryValue
* dict
=
427 local_state
->GetDictionary(prefs::kEasyUnlockHardlockState
);
429 if (dict
&& dict
->GetIntegerWithoutPathExpansion(user_id
, &state_int
)) {
431 static_cast<EasyUnlockScreenlockStateHandler::HardlockState
>(state_int
);
438 void EasyUnlockService::ShowInitialUserState() {
439 if (!GetScreenlockStateHandler())
442 EasyUnlockScreenlockStateHandler::HardlockState state
;
443 bool has_persisted_state
= GetPersistedHardlockState(&state
);
444 if (!has_persisted_state
)
447 if (state
== EasyUnlockScreenlockStateHandler::NO_HARDLOCK
) {
448 // Show connecting icon early when there is a persisted non hardlock state.
449 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING
);
451 screenlock_state_handler_
->MaybeShowHardlockUI();
455 EasyUnlockScreenlockStateHandler
*
456 EasyUnlockService::GetScreenlockStateHandler() {
459 if (!screenlock_state_handler_
) {
460 screenlock_state_handler_
.reset(new EasyUnlockScreenlockStateHandler(
461 GetUserEmail(), GetHardlockState(),
462 proximity_auth::ScreenlockBridge::Get()));
464 return screenlock_state_handler_
.get();
467 bool EasyUnlockService::UpdateScreenlockState(ScreenlockState state
) {
468 EasyUnlockScreenlockStateHandler
* handler
= GetScreenlockStateHandler();
472 handler
->ChangeState(state
);
474 if (state
== ScreenlockState::AUTHENTICATED
) {
475 #if defined(OS_CHROMEOS)
477 power_monitor_
->RecordStartUpTime();
479 } else if (auth_attempt_
.get()) {
480 // Clean up existing auth attempt if we can no longer authenticate the
482 auth_attempt_
.reset();
484 if (!handler
->InStateValidOnRemoteAuthFailure())
485 HandleAuthFailure(GetUserEmail());
489 EasyUnlockServiceObserver
, observers_
, OnScreenlockStateChanged(state
));
493 ScreenlockState
EasyUnlockService::GetScreenlockState() {
494 EasyUnlockScreenlockStateHandler
* handler
= GetScreenlockStateHandler();
496 return ScreenlockState::INACTIVE
;
498 return handler
->state();
501 void EasyUnlockService::AttemptAuth(const std::string
& user_id
) {
502 AttemptAuth(user_id
, AttemptAuthCallback());
505 void EasyUnlockService::AttemptAuth(const std::string
& user_id
,
506 const AttemptAuthCallback
& callback
) {
507 const EasyUnlockAuthAttempt::Type auth_attempt_type
=
508 GetType() == TYPE_REGULAR
? EasyUnlockAuthAttempt::TYPE_UNLOCK
509 : EasyUnlockAuthAttempt::TYPE_SIGNIN
;
510 const std::string user_email
= GetUserEmail();
511 if (user_email
.empty()) {
512 LOG(ERROR
) << "Empty user email. Refresh token might go bad.";
513 if (!callback
.is_null()) {
514 const bool kFailure
= false;
515 callback
.Run(auth_attempt_type
, kFailure
, user_id
, std::string(),
521 CHECK_EQ(GetUserEmail(), user_id
);
523 auth_attempt_
.reset(new EasyUnlockAuthAttempt(app_manager_
.get(), user_id
,
524 auth_attempt_type
, callback
));
525 if (!auth_attempt_
->Start())
526 auth_attempt_
.reset();
528 // TODO(tengs): We notify ProximityAuthBleSystem whenever unlock attempts are
529 // attempted. However, we ideally should refactor the auth attempt logic to
530 // the proximity_auth component.
531 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
532 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery
) &&
533 auth_attempt_type
== EasyUnlockAuthAttempt::TYPE_UNLOCK
&&
534 proximity_auth_ble_system_
) {
535 proximity_auth_ble_system_
->OnAuthAttempted(user_id
);
539 void EasyUnlockService::FinalizeUnlock(bool success
) {
540 if (!auth_attempt_
.get())
543 this->OnWillFinalizeUnlock(success
);
544 auth_attempt_
->FinalizeUnlock(GetUserEmail(), success
);
545 auth_attempt_
.reset();
546 // TODO(isherman): If observing screen unlock events, is there a race
547 // condition in terms of reading the service's state vs. the app setting the
550 // Make sure that the lock screen is updated on failure.
552 RecordEasyUnlockScreenUnlockEvent(EASY_UNLOCK_FAILURE
);
553 HandleAuthFailure(GetUserEmail());
557 void EasyUnlockService::FinalizeSignin(const std::string
& key
) {
558 if (!auth_attempt_
.get())
560 std::string wrapped_secret
= GetWrappedSecret();
561 if (!wrapped_secret
.empty())
562 auth_attempt_
->FinalizeSignin(GetUserEmail(), wrapped_secret
, key
);
563 auth_attempt_
.reset();
565 // Processing empty key is equivalent to auth cancellation. In this case the
566 // signin request will not actually be processed by login stack, so the lock
567 // screen state should be set from here.
569 HandleAuthFailure(GetUserEmail());
572 void EasyUnlockService::HandleAuthFailure(const std::string
& user_id
) {
573 if (user_id
!= GetUserEmail())
576 if (!screenlock_state_handler_
.get())
579 screenlock_state_handler_
->SetHardlockState(
580 EasyUnlockScreenlockStateHandler::LOGIN_FAILED
);
583 void EasyUnlockService::CheckCryptohomeKeysAndMaybeHardlock() {
584 #if defined(OS_CHROMEOS)
585 std::string user_id
= GetUserEmail();
589 const base::ListValue
* device_list
= GetRemoteDevices();
590 std::set
<std::string
> paired_devices
;
592 chromeos::EasyUnlockDeviceKeyDataList parsed_paired
;
593 chromeos::EasyUnlockKeyManager::RemoteDeviceListToDeviceDataList(
594 *device_list
, &parsed_paired
);
595 for (const auto& device_key_data
: parsed_paired
)
596 paired_devices
.insert(device_key_data
.psk
);
598 if (paired_devices
.empty()) {
599 SetHardlockState(EasyUnlockScreenlockStateHandler::NO_PAIRING
);
603 // No need to compare if a change is already recorded.
604 if (GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_CHANGED
||
605 GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_ADDED
) {
609 chromeos::EasyUnlockKeyManager
* key_manager
=
610 chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager();
613 key_manager
->GetDeviceDataList(
614 chromeos::UserContext(user_id
),
615 base::Bind(&EasyUnlockService::OnCryptohomeKeysFetchedForChecking
,
616 weak_ptr_factory_
.GetWeakPtr(),
622 void EasyUnlockService::SetTrialRun() {
623 DCHECK_EQ(GetType(), TYPE_REGULAR
);
625 EasyUnlockScreenlockStateHandler
* handler
= GetScreenlockStateHandler();
627 handler
->SetTrialRun();
630 void EasyUnlockService::RecordClickOnLockIcon() {
631 if (screenlock_state_handler_
)
632 screenlock_state_handler_
->RecordClickOnLockIcon();
635 void EasyUnlockService::AddObserver(EasyUnlockServiceObserver
* observer
) {
636 observers_
.AddObserver(observer
);
639 void EasyUnlockService::RemoveObserver(EasyUnlockServiceObserver
* observer
) {
640 observers_
.RemoveObserver(observer
);
643 void EasyUnlockService::Shutdown() {
650 ResetScreenlockState();
651 bluetooth_detector_
.reset();
652 #if defined(OS_CHROMEOS)
653 power_monitor_
.reset();
656 weak_ptr_factory_
.InvalidateWeakPtrs();
659 void EasyUnlockService::ReloadAppAndLockScreen() {
660 // Make sure lock screen state set by the extension gets reset.
661 ResetScreenlockState();
662 app_manager_
->ReloadApp();
666 void EasyUnlockService::UpdateAppState() {
668 EnsureTpmKeyPresentIfNeeded();
669 app_manager_
->LoadApp();
672 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
673 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery
) &&
674 GetType() == EasyUnlockService::TYPE_REGULAR
&&
675 !proximity_auth_ble_system_
) {
676 proximity_auth_ble_system_
.reset(
677 new proximity_auth::ProximityAuthBleSystem(
678 proximity_auth::ScreenlockBridge::Get(), &proximity_auth_client_
,
679 profile_
->GetPrefs()));
682 #if defined(OS_CHROMEOS)
684 power_monitor_
.reset(new PowerMonitor(this));
687 bool bluetooth_waking_up
= false;
688 #if defined(OS_CHROMEOS)
689 // If the service is not allowed due to bluetooth not being detected just
690 // after system suspend is done, give bluetooth more time to be detected
691 // before disabling the app (and resetting screenlock state).
692 bluetooth_waking_up
=
693 power_monitor_
.get() && power_monitor_
->waking_up() &&
694 !bluetooth_detector_
->IsPresent();
697 if (!bluetooth_waking_up
) {
698 app_manager_
->DisableAppIfLoaded();
699 ResetScreenlockState();
700 proximity_auth_ble_system_
.reset();
701 #if defined(OS_CHROMEOS)
702 power_monitor_
.reset();
708 void EasyUnlockService::DisableAppWithoutResettingScreenlockState() {
709 app_manager_
->DisableAppIfLoaded();
712 void EasyUnlockService::NotifyUserUpdated() {
713 std::string user_id
= GetUserEmail();
717 // Notify the easy unlock app that the user info changed.
718 bool logged_in
= GetType() == TYPE_REGULAR
;
719 bool data_ready
= logged_in
|| GetRemoteDevices() != NULL
;
720 app_manager_
->SendUserUpdatedEvent(user_id
, logged_in
, data_ready
);
723 void EasyUnlockService::NotifyTurnOffOperationStatusChanged() {
725 EasyUnlockServiceObserver
, observers_
, OnTurnOffOperationStatusChanged());
728 void EasyUnlockService::ResetScreenlockState() {
729 screenlock_state_handler_
.reset();
730 auth_attempt_
.reset();
733 void EasyUnlockService::SetScreenlockHardlockedState(
734 EasyUnlockScreenlockStateHandler::HardlockState state
) {
735 if (screenlock_state_handler_
)
736 screenlock_state_handler_
->SetHardlockState(state
);
737 if (state
!= EasyUnlockScreenlockStateHandler::NO_HARDLOCK
)
738 auth_attempt_
.reset();
741 void EasyUnlockService::InitializeOnAppManagerReady() {
742 CHECK(app_manager_
.get());
744 InitializeInternal();
745 bluetooth_detector_
->Initialize();
748 void EasyUnlockService::OnBluetoothAdapterPresentChanged() {
751 // Whether we've already passed Bluetooth availability information to UMA.
752 // This is static because there may be multiple instances and we want to
753 // report this system-level stat only once per run of Chrome.
754 static bool bluetooth_adapter_has_been_reported
= false;
756 if (!bluetooth_adapter_has_been_reported
) {
757 bluetooth_adapter_has_been_reported
= true;
758 int bttype
= BT_NO_ADAPTER
;
759 if (bluetooth_detector_
->IsPresent()) {
760 bttype
= BT_LOW_ENERGY_CAPABLE
;
762 if (base::win::GetVersion() < base::win::VERSION_WIN8
) {
767 UMA_HISTOGRAM_ENUMERATION(
768 "EasyUnlock.BluetoothAvailability", bttype
, BT_MAX_TYPE
);
772 void EasyUnlockService::SetHardlockStateForUser(
773 const std::string
& user_id
,
774 EasyUnlockScreenlockStateHandler::HardlockState state
) {
775 DCHECK(!user_id
.empty());
777 PrefService
* local_state
= GetLocalState();
781 DictionaryPrefUpdate
update(local_state
, prefs::kEasyUnlockHardlockState
);
782 update
->SetIntegerWithoutPathExpansion(user_id
, static_cast<int>(state
));
784 if (GetUserEmail() == user_id
)
785 SetScreenlockHardlockedState(state
);
788 EasyUnlockAuthEvent
EasyUnlockService::GetPasswordAuthEvent() const {
791 if (GetHardlockState() != EasyUnlockScreenlockStateHandler::NO_HARDLOCK
) {
792 switch (GetHardlockState()) {
793 case EasyUnlockScreenlockStateHandler::NO_HARDLOCK
:
795 return EASY_UNLOCK_AUTH_EVENT_COUNT
;
796 case EasyUnlockScreenlockStateHandler::NO_PAIRING
:
797 return PASSWORD_ENTRY_NO_PAIRING
;
798 case EasyUnlockScreenlockStateHandler::USER_HARDLOCK
:
799 return PASSWORD_ENTRY_USER_HARDLOCK
;
800 case EasyUnlockScreenlockStateHandler::PAIRING_CHANGED
:
801 return PASSWORD_ENTRY_PAIRING_CHANGED
;
802 case EasyUnlockScreenlockStateHandler::LOGIN_FAILED
:
803 return PASSWORD_ENTRY_LOGIN_FAILED
;
804 case EasyUnlockScreenlockStateHandler::PAIRING_ADDED
:
805 return PASSWORD_ENTRY_PAIRING_ADDED
;
807 } else if (!screenlock_state_handler()) {
808 return PASSWORD_ENTRY_NO_SCREENLOCK_STATE_HANDLER
;
810 switch (screenlock_state_handler()->state()) {
811 case ScreenlockState::INACTIVE
:
812 return PASSWORD_ENTRY_SERVICE_NOT_ACTIVE
;
813 case ScreenlockState::NO_BLUETOOTH
:
814 return PASSWORD_ENTRY_NO_BLUETOOTH
;
815 case ScreenlockState::BLUETOOTH_CONNECTING
:
816 return PASSWORD_ENTRY_BLUETOOTH_CONNECTING
;
817 case ScreenlockState::NO_PHONE
:
818 return PASSWORD_ENTRY_NO_PHONE
;
819 case ScreenlockState::PHONE_NOT_AUTHENTICATED
:
820 return PASSWORD_ENTRY_PHONE_NOT_AUTHENTICATED
;
821 case ScreenlockState::PHONE_LOCKED
:
822 return PASSWORD_ENTRY_PHONE_LOCKED
;
823 case ScreenlockState::PHONE_NOT_LOCKABLE
:
824 return PASSWORD_ENTRY_PHONE_NOT_LOCKABLE
;
825 case ScreenlockState::PHONE_UNSUPPORTED
:
826 return PASSWORD_ENTRY_PHONE_UNSUPPORTED
;
827 case ScreenlockState::RSSI_TOO_LOW
:
828 return PASSWORD_ENTRY_RSSI_TOO_LOW
;
829 case ScreenlockState::TX_POWER_TOO_HIGH
:
830 return PASSWORD_ENTRY_TX_POWER_TOO_HIGH
;
831 case ScreenlockState::PHONE_LOCKED_AND_TX_POWER_TOO_HIGH
:
832 return PASSWORD_ENTRY_PHONE_LOCKED_AND_TX_POWER_TOO_HIGH
;
833 case ScreenlockState::AUTHENTICATED
:
834 return PASSWORD_ENTRY_WITH_AUTHENTICATED_PHONE
;
839 return EASY_UNLOCK_AUTH_EVENT_COUNT
;
842 #if defined(OS_CHROMEOS)
843 void EasyUnlockService::OnCryptohomeKeysFetchedForChecking(
844 const std::string
& user_id
,
845 const std::set
<std::string
> paired_devices
,
847 const chromeos::EasyUnlockDeviceKeyDataList
& key_data_list
) {
848 DCHECK(!user_id
.empty() && !paired_devices
.empty());
851 SetHardlockStateForUser(user_id
,
852 EasyUnlockScreenlockStateHandler::NO_PAIRING
);
856 std::set
<std::string
> devices_in_cryptohome
;
857 for (const auto& device_key_data
: key_data_list
)
858 devices_in_cryptohome
.insert(device_key_data
.psk
);
860 if (paired_devices
!= devices_in_cryptohome
||
861 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING
) {
862 SetHardlockStateForUser(
864 devices_in_cryptohome
.empty()
865 ? EasyUnlockScreenlockStateHandler::PAIRING_ADDED
866 : EasyUnlockScreenlockStateHandler::PAIRING_CHANGED
);
871 void EasyUnlockService::PrepareForSuspend() {
872 app_manager_
->DisableAppIfLoaded();
873 if (screenlock_state_handler_
&& screenlock_state_handler_
->IsActive())
874 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING
);
877 void EasyUnlockService::EnsureTpmKeyPresentIfNeeded() {
878 if (tpm_key_checked_
|| GetType() != TYPE_REGULAR
|| GetUserEmail().empty() ||
879 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING
) {
883 #if defined(OS_CHROMEOS)
884 // If this is called before the session is started, the chances are Chrome
885 // is restarting in order to apply user flags. Don't check TPM keys in this
887 if (!user_manager::UserManager::Get() ||
888 !user_manager::UserManager::Get()->IsSessionStarted())
891 // TODO(tbarzic): Set check_private_key only if previous sign-in attempt
893 EasyUnlockTpmKeyManagerFactory::GetInstance()->Get(profile_
)
894 ->PrepareTpmKey(true /* check_private_key */,
896 #endif // defined(OS_CHROMEOS)
898 tpm_key_checked_
= true;