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/easy_unlock_app_manager.h"
25 #include "chrome/browser/signin/easy_unlock_service_factory.h"
26 #include "chrome/browser/signin/easy_unlock_service_observer.h"
27 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
28 #include "chrome/browser/signin/proximity_auth_facade.h"
29 #include "chrome/browser/signin/signin_manager_factory.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/chrome_version_info.h"
32 #include "chrome/common/extensions/extension_constants.h"
33 #include "chrome/common/pref_names.h"
34 #include "components/pref_registry/pref_registry_syncable.h"
35 #include "components/proximity_auth/ble/proximity_auth_ble_system.h"
36 #include "components/proximity_auth/cryptauth/cryptauth_client_impl.h"
37 #include "components/proximity_auth/screenlock_bridge.h"
38 #include "components/proximity_auth/switches.h"
39 #include "components/signin/core/browser/profile_oauth2_token_service.h"
40 #include "components/signin/core/browser/signin_manager.h"
41 #include "components/user_manager/user.h"
42 #include "device/bluetooth/bluetooth_adapter.h"
43 #include "device/bluetooth/bluetooth_adapter_factory.h"
45 #if defined(OS_CHROMEOS)
46 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
47 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
48 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
49 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
50 #include "chrome/browser/chromeos/profiles/profile_helper.h"
51 #include "chromeos/dbus/dbus_thread_manager.h"
52 #include "chromeos/dbus/power_manager_client.h"
53 #include "components/user_manager/user_manager.h"
57 #include "base/win/windows_version.h"
60 using proximity_auth::ScreenlockState
;
67 BT_LOW_ENERGY_CAPABLE
,
71 PrefService
* GetLocalState() {
72 return g_browser_process
? g_browser_process
->local_state() : NULL
;
77 EasyUnlockService::UserSettings::UserSettings()
78 : require_close_proximity(false) {
81 EasyUnlockService::UserSettings::~UserSettings() {
85 EasyUnlockService
* EasyUnlockService::Get(Profile
* profile
) {
86 return EasyUnlockServiceFactory::GetForBrowserContext(profile
);
90 EasyUnlockService
* EasyUnlockService::GetForUser(
91 const user_manager::User
& user
) {
92 #if defined(OS_CHROMEOS)
93 Profile
* profile
= chromeos::ProfileHelper::Get()->GetProfileByUser(&user
);
96 return EasyUnlockService::Get(profile
);
103 bool EasyUnlockService::IsSignInEnabled() {
104 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
105 proximity_auth::switches::kDisableEasyUnlock
);
108 class EasyUnlockService::BluetoothDetector
109 : public device::BluetoothAdapter::Observer
,
110 public apps::AppLifetimeMonitor::Observer
{
112 explicit BluetoothDetector(EasyUnlockService
* service
)
114 weak_ptr_factory_(this) {
115 apps::AppLifetimeMonitorFactory::GetForProfile(service_
->profile())
119 ~BluetoothDetector() override
{
121 adapter_
->RemoveObserver(this);
122 apps::AppLifetimeMonitorFactory::GetForProfile(service_
->profile())
123 ->RemoveObserver(this);
127 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
130 device::BluetoothAdapterFactory::GetAdapter(
131 base::Bind(&BluetoothDetector::OnAdapterInitialized
,
132 weak_ptr_factory_
.GetWeakPtr()));
135 bool IsPresent() const { return adapter_
.get() && adapter_
->IsPresent(); }
137 // device::BluetoothAdapter::Observer:
138 void AdapterPresentChanged(device::BluetoothAdapter
* adapter
,
139 bool present
) override
{
140 service_
->OnBluetoothAdapterPresentChanged();
143 device::BluetoothAdapter
* getAdapter() {
144 return adapter_
.get();
148 void OnAdapterInitialized(scoped_refptr
<device::BluetoothAdapter
> adapter
) {
150 adapter_
->AddObserver(this);
151 service_
->OnBluetoothAdapterPresentChanged();
153 #if !defined(OS_CHROMEOS)
154 // Bluetooth detection causes serious performance degradations on Mac
155 // and possibly other platforms as well: http://crbug.com/467316
156 // Since this feature is currently only offered for ChromeOS we just
157 // turn it off on other platforms once the inforamtion about the
158 // adapter has been gathered and reported.
159 // TODO(bcwhite,xiyuan): Revisit when non-chromeos platforms are supported.
160 adapter_
->RemoveObserver(this);
163 // TODO(tengs): At the moment, there is no way for Bluetooth discoverability
164 // to be turned on except through the Easy Unlock setup. If we step on any
165 // toes in the future then we need to revisit this guard.
166 if (adapter_
->IsDiscoverable())
167 TurnOffBluetoothDiscoverability();
168 #endif // !defined(OS_CHROMEOS)
171 // apps::AppLifetimeMonitor::Observer:
172 void OnAppDeactivated(Profile
* profile
, const std::string
& app_id
) override
{
173 // TODO(tengs): Refactor the lifetime management to EasyUnlockAppManager.
174 if (app_id
== extension_misc::kEasyUnlockAppId
)
175 TurnOffBluetoothDiscoverability();
178 void OnAppStop(Profile
* profile
, const std::string
& app_id
) override
{
179 // TODO(tengs): Refactor the lifetime management to EasyUnlockAppManager.
180 if (app_id
== extension_misc::kEasyUnlockAppId
)
181 TurnOffBluetoothDiscoverability();
184 void TurnOffBluetoothDiscoverability() {
186 adapter_
->SetDiscoverable(
187 false, base::Bind(&base::DoNothing
), base::Bind(&base::DoNothing
));
191 // Owner of this class and should out-live this class.
192 EasyUnlockService
* service_
;
193 scoped_refptr
<device::BluetoothAdapter
> adapter_
;
194 base::WeakPtrFactory
<BluetoothDetector
> weak_ptr_factory_
;
196 DISALLOW_COPY_AND_ASSIGN(BluetoothDetector
);
199 #if defined(OS_CHROMEOS)
200 class EasyUnlockService::PowerMonitor
201 : public chromeos::PowerManagerClient::Observer
{
203 explicit PowerMonitor(EasyUnlockService
* service
)
206 weak_ptr_factory_(this) {
207 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
211 ~PowerMonitor() override
{
212 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
213 RemoveObserver(this);
216 // Called when the remote device has been authenticated to record the time
217 // delta from waking up. No time will be recorded if the start-up time has
218 // already been recorded or if the system never went to sleep previously.
219 void RecordStartUpTime() {
220 if (wake_up_time_
.is_null())
222 UMA_HISTOGRAM_MEDIUM_TIMES(
223 "EasyUnlock.StartupTimeFromSuspend",
224 base::Time::Now() - wake_up_time_
);
225 wake_up_time_
= base::Time();
228 bool waking_up() const { return waking_up_
; }
231 // chromeos::PowerManagerClient::Observer:
232 void SuspendImminent() override
{ service_
->PrepareForSuspend(); }
234 void SuspendDone(const base::TimeDelta
& sleep_duration
) override
{
236 wake_up_time_
= base::Time::Now();
237 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
239 base::Bind(&PowerMonitor::ResetWakingUp
,
240 weak_ptr_factory_
.GetWeakPtr()),
241 base::TimeDelta::FromSeconds(5));
242 service_
->OnSuspendDone();
243 service_
->UpdateAppState();
244 // Note that |this| may get deleted after |UpdateAppState| is called.
247 void ResetWakingUp() {
249 service_
->UpdateAppState();
252 EasyUnlockService
* service_
;
254 base::Time wake_up_time_
;
255 base::WeakPtrFactory
<PowerMonitor
> weak_ptr_factory_
;
257 DISALLOW_COPY_AND_ASSIGN(PowerMonitor
);
261 EasyUnlockService::EasyUnlockService(Profile
* profile
)
263 bluetooth_detector_(new BluetoothDetector(this)),
265 tpm_key_checked_(false),
266 weak_ptr_factory_(this) {
269 EasyUnlockService::~EasyUnlockService() {
273 void EasyUnlockService::RegisterProfilePrefs(
274 user_prefs::PrefRegistrySyncable
* registry
) {
275 registry
->RegisterBooleanPref(prefs::kEasyUnlockAllowed
, true);
276 registry
->RegisterBooleanPref(prefs::kEasyUnlockEnabled
, false);
277 registry
->RegisterDictionaryPref(prefs::kEasyUnlockPairing
,
278 new base::DictionaryValue());
279 registry
->RegisterBooleanPref(
280 prefs::kEasyUnlockProximityRequired
,
282 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
286 void EasyUnlockService::RegisterPrefs(PrefRegistrySimple
* registry
) {
287 registry
->RegisterStringPref(prefs::kEasyUnlockDeviceId
, std::string());
288 registry
->RegisterDictionaryPref(prefs::kEasyUnlockHardlockState
);
289 registry
->RegisterDictionaryPref(prefs::kEasyUnlockLocalStateUserPrefs
);
290 #if defined(OS_CHROMEOS)
291 EasyUnlockTpmKeyManager::RegisterLocalStatePrefs(registry
);
296 void EasyUnlockService::ResetLocalStateForUser(const std::string
& user_id
) {
297 DCHECK(!user_id
.empty());
299 PrefService
* local_state
= GetLocalState();
303 DictionaryPrefUpdate
update(local_state
, prefs::kEasyUnlockHardlockState
);
304 update
->RemoveWithoutPathExpansion(user_id
, NULL
);
306 #if defined(OS_CHROMEOS)
307 EasyUnlockTpmKeyManager::ResetLocalStateForUser(user_id
);
312 EasyUnlockService::UserSettings
EasyUnlockService::GetUserSettings(
313 const std::string
& user_id
) {
314 DCHECK(!user_id
.empty());
315 UserSettings user_settings
;
317 PrefService
* local_state
= GetLocalState();
319 return user_settings
;
321 const base::DictionaryValue
* all_user_prefs_dict
=
322 local_state
->GetDictionary(prefs::kEasyUnlockLocalStateUserPrefs
);
323 if (!all_user_prefs_dict
)
324 return user_settings
;
326 const base::DictionaryValue
* user_prefs_dict
;
327 if (!all_user_prefs_dict
->GetDictionaryWithoutPathExpansion(user_id
,
329 return user_settings
;
331 user_prefs_dict
->GetBooleanWithoutPathExpansion(
332 prefs::kEasyUnlockProximityRequired
,
333 &user_settings
.require_close_proximity
);
335 return user_settings
;
339 std::string
EasyUnlockService::GetDeviceId() {
340 PrefService
* local_state
= GetLocalState();
342 return std::string();
344 std::string device_id
= local_state
->GetString(prefs::kEasyUnlockDeviceId
);
345 if (device_id
.empty()) {
346 device_id
= base::GenerateGUID();
347 local_state
->SetString(prefs::kEasyUnlockDeviceId
, device_id
);
352 void EasyUnlockService::Initialize(
353 scoped_ptr
<EasyUnlockAppManager
> app_manager
) {
354 app_manager_
= app_manager
.Pass();
355 app_manager_
->EnsureReady(
356 base::Bind(&EasyUnlockService::InitializeOnAppManagerReady
,
357 weak_ptr_factory_
.GetWeakPtr()));
360 bool EasyUnlockService::IsAllowed() const {
364 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
365 proximity_auth::switches::kDisableEasyUnlock
)) {
369 if (!IsAllowedInternal())
372 #if defined(OS_CHROMEOS)
373 if (!bluetooth_detector_
->IsPresent())
378 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
383 bool EasyUnlockService::IsEnabled() const {
384 // The feature is enabled iff there are any paired devices.
385 const base::ListValue
* devices
= GetRemoteDevices();
386 return devices
&& !devices
->empty();
389 void EasyUnlockService::OpenSetupApp() {
390 app_manager_
->LaunchSetup();
393 void EasyUnlockService::SetHardlockState(
394 EasyUnlockScreenlockStateHandler::HardlockState state
) {
395 const std::string user_id
= GetUserEmail();
399 if (state
== GetHardlockState())
402 SetHardlockStateForUser(user_id
, state
);
405 EasyUnlockScreenlockStateHandler::HardlockState
406 EasyUnlockService::GetHardlockState() const {
407 EasyUnlockScreenlockStateHandler::HardlockState state
;
408 if (GetPersistedHardlockState(&state
))
411 return EasyUnlockScreenlockStateHandler::NO_HARDLOCK
;
414 bool EasyUnlockService::GetPersistedHardlockState(
415 EasyUnlockScreenlockStateHandler::HardlockState
* state
) const {
416 std::string user_id
= GetUserEmail();
420 PrefService
* local_state
= GetLocalState();
424 const base::DictionaryValue
* dict
=
425 local_state
->GetDictionary(prefs::kEasyUnlockHardlockState
);
427 if (dict
&& dict
->GetIntegerWithoutPathExpansion(user_id
, &state_int
)) {
429 static_cast<EasyUnlockScreenlockStateHandler::HardlockState
>(state_int
);
436 void EasyUnlockService::ShowInitialUserState() {
437 if (!GetScreenlockStateHandler())
440 EasyUnlockScreenlockStateHandler::HardlockState state
;
441 bool has_persisted_state
= GetPersistedHardlockState(&state
);
442 if (!has_persisted_state
)
445 if (state
== EasyUnlockScreenlockStateHandler::NO_HARDLOCK
) {
446 // Show connecting icon early when there is a persisted non hardlock state.
447 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING
);
449 screenlock_state_handler_
->MaybeShowHardlockUI();
453 EasyUnlockScreenlockStateHandler
*
454 EasyUnlockService::GetScreenlockStateHandler() {
457 if (!screenlock_state_handler_
) {
458 screenlock_state_handler_
.reset(new EasyUnlockScreenlockStateHandler(
459 GetUserEmail(), GetHardlockState(), GetScreenlockBridgeInstance()));
461 return screenlock_state_handler_
.get();
464 bool EasyUnlockService::UpdateScreenlockState(ScreenlockState state
) {
465 EasyUnlockScreenlockStateHandler
* handler
= GetScreenlockStateHandler();
469 handler
->ChangeState(state
);
471 if (state
== ScreenlockState::AUTHENTICATED
) {
472 #if defined(OS_CHROMEOS)
474 power_monitor_
->RecordStartUpTime();
476 } else if (auth_attempt_
.get()) {
477 // Clean up existing auth attempt if we can no longer authenticate the
479 auth_attempt_
.reset();
481 if (!handler
->InStateValidOnRemoteAuthFailure())
482 HandleAuthFailure(GetUserEmail());
486 EasyUnlockServiceObserver
, observers_
, OnScreenlockStateChanged(state
));
490 ScreenlockState
EasyUnlockService::GetScreenlockState() {
491 EasyUnlockScreenlockStateHandler
* handler
= GetScreenlockStateHandler();
493 return ScreenlockState::INACTIVE
;
495 return handler
->state();
498 void EasyUnlockService::AttemptAuth(const std::string
& user_id
) {
499 AttemptAuth(user_id
, AttemptAuthCallback());
502 void EasyUnlockService::AttemptAuth(const std::string
& user_id
,
503 const AttemptAuthCallback
& callback
) {
504 const EasyUnlockAuthAttempt::Type auth_attempt_type
=
505 GetType() == TYPE_REGULAR
? EasyUnlockAuthAttempt::TYPE_UNLOCK
506 : EasyUnlockAuthAttempt::TYPE_SIGNIN
;
507 const std::string user_email
= GetUserEmail();
508 if (user_email
.empty()) {
509 LOG(ERROR
) << "Empty user email. Refresh token might go bad.";
510 if (!callback
.is_null()) {
511 const bool kFailure
= false;
512 callback
.Run(auth_attempt_type
, kFailure
, user_id
, std::string(),
518 CHECK_EQ(GetUserEmail(), user_id
);
520 auth_attempt_
.reset(new EasyUnlockAuthAttempt(app_manager_
.get(), user_id
,
521 auth_attempt_type
, callback
));
522 if (!auth_attempt_
->Start())
523 auth_attempt_
.reset();
526 void EasyUnlockService::FinalizeUnlock(bool success
) {
527 if (!auth_attempt_
.get())
530 this->OnWillFinalizeUnlock(success
);
531 auth_attempt_
->FinalizeUnlock(GetUserEmail(), success
);
532 auth_attempt_
.reset();
533 // TODO(isherman): If observing screen unlock events, is there a race
534 // condition in terms of reading the service's state vs. the app setting the
537 // Make sure that the lock screen is updated on failure.
539 RecordEasyUnlockScreenUnlockEvent(EASY_UNLOCK_FAILURE
);
540 HandleAuthFailure(GetUserEmail());
544 void EasyUnlockService::FinalizeSignin(const std::string
& key
) {
545 if (!auth_attempt_
.get())
547 std::string wrapped_secret
= GetWrappedSecret();
548 if (!wrapped_secret
.empty())
549 auth_attempt_
->FinalizeSignin(GetUserEmail(), wrapped_secret
, key
);
550 auth_attempt_
.reset();
552 // Processing empty key is equivalent to auth cancellation. In this case the
553 // signin request will not actually be processed by login stack, so the lock
554 // screen state should be set from here.
556 HandleAuthFailure(GetUserEmail());
559 void EasyUnlockService::HandleAuthFailure(const std::string
& user_id
) {
560 if (user_id
!= GetUserEmail())
563 if (!screenlock_state_handler_
.get())
566 screenlock_state_handler_
->SetHardlockState(
567 EasyUnlockScreenlockStateHandler::LOGIN_FAILED
);
570 void EasyUnlockService::CheckCryptohomeKeysAndMaybeHardlock() {
571 #if defined(OS_CHROMEOS)
572 std::string user_id
= GetUserEmail();
576 const base::ListValue
* device_list
= GetRemoteDevices();
577 std::set
<std::string
> paired_devices
;
579 chromeos::EasyUnlockDeviceKeyDataList parsed_paired
;
580 chromeos::EasyUnlockKeyManager::RemoteDeviceListToDeviceDataList(
581 *device_list
, &parsed_paired
);
582 for (const auto& device_key_data
: parsed_paired
)
583 paired_devices
.insert(device_key_data
.psk
);
585 if (paired_devices
.empty()) {
586 SetHardlockState(EasyUnlockScreenlockStateHandler::NO_PAIRING
);
590 // No need to compare if a change is already recorded.
591 if (GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_CHANGED
||
592 GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_ADDED
) {
596 chromeos::EasyUnlockKeyManager
* key_manager
=
597 chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager();
600 key_manager
->GetDeviceDataList(
601 chromeos::UserContext(user_id
),
602 base::Bind(&EasyUnlockService::OnCryptohomeKeysFetchedForChecking
,
603 weak_ptr_factory_
.GetWeakPtr(),
609 void EasyUnlockService::SetTrialRun() {
610 DCHECK_EQ(GetType(), TYPE_REGULAR
);
612 EasyUnlockScreenlockStateHandler
* handler
= GetScreenlockStateHandler();
614 handler
->SetTrialRun();
617 void EasyUnlockService::RecordClickOnLockIcon() {
618 if (screenlock_state_handler_
)
619 screenlock_state_handler_
->RecordClickOnLockIcon();
622 void EasyUnlockService::AddObserver(EasyUnlockServiceObserver
* observer
) {
623 observers_
.AddObserver(observer
);
626 void EasyUnlockService::RemoveObserver(EasyUnlockServiceObserver
* observer
) {
627 observers_
.RemoveObserver(observer
);
630 scoped_ptr
<proximity_auth::CryptAuthClientFactory
>
631 EasyUnlockService::CreateCryptAuthClientFactory() {
632 return make_scoped_ptr(new proximity_auth::CryptAuthClientFactoryImpl(
633 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()),
634 SigninManagerFactory::GetForProfile(profile())
635 ->GetAuthenticatedAccountId(),
636 profile()->GetRequestContext(), GetDeviceClassifier()));
639 cryptauth::DeviceClassifier
EasyUnlockService::GetDeviceClassifier() {
640 cryptauth::DeviceClassifier device_classifier
;
642 #if defined(OS_CHROMEOS)
643 int32 major_version
, minor_version
, bugfix_version
;
644 // TODO(tengs): base::OperatingSystemVersionNumbers only works for ChromeOS.
645 // We need to get different numbers for other platforms.
646 base::SysInfo::OperatingSystemVersionNumbers(&major_version
, &minor_version
,
648 device_classifier
.set_device_os_version_code(major_version
);
649 device_classifier
.set_device_type(cryptauth::CHROME
);
652 chrome::VersionInfo version_info
;
653 const std::vector
<uint32_t>& version_components
=
654 base::Version(version_info
.Version()).components();
655 if (version_components
.size() > 0)
656 device_classifier
.set_device_software_version_code(version_components
[0]);
658 device_classifier
.set_device_software_package(version_info
.Name());
659 return device_classifier
;
662 void EasyUnlockService::Shutdown() {
669 ResetScreenlockState();
670 bluetooth_detector_
.reset();
671 #if defined(OS_CHROMEOS)
672 power_monitor_
.reset();
675 weak_ptr_factory_
.InvalidateWeakPtrs();
678 void EasyUnlockService::ReloadAppAndLockScreen() {
679 // Make sure lock screen state set by the extension gets reset.
680 ResetScreenlockState();
681 app_manager_
->ReloadApp();
685 void EasyUnlockService::UpdateAppState() {
687 EnsureTpmKeyPresentIfNeeded();
688 app_manager_
->LoadApp();
691 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
692 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery
) &&
693 GetType() == EasyUnlockService::TYPE_REGULAR
&&
694 !proximity_auth_ble_system_
) {
695 proximity_auth_ble_system_
.reset(
696 new proximity_auth::ProximityAuthBleSystem(
697 GetScreenlockBridgeInstance(), profile_
,
698 CreateCryptAuthClientFactory()));
701 #if defined(OS_CHROMEOS)
703 power_monitor_
.reset(new PowerMonitor(this));
706 bool bluetooth_waking_up
= false;
707 #if defined(OS_CHROMEOS)
708 // If the service is not allowed due to bluetooth not being detected just
709 // after system suspend is done, give bluetooth more time to be detected
710 // before disabling the app (and resetting screenlock state).
711 bluetooth_waking_up
=
712 power_monitor_
.get() && power_monitor_
->waking_up() &&
713 !bluetooth_detector_
->IsPresent();
716 if (!bluetooth_waking_up
) {
717 app_manager_
->DisableAppIfLoaded();
718 ResetScreenlockState();
719 proximity_auth_ble_system_
.reset();
720 #if defined(OS_CHROMEOS)
721 power_monitor_
.reset();
727 void EasyUnlockService::DisableAppWithoutResettingScreenlockState() {
728 app_manager_
->DisableAppIfLoaded();
731 void EasyUnlockService::NotifyUserUpdated() {
732 std::string user_id
= GetUserEmail();
736 // Notify the easy unlock app that the user info changed.
737 bool logged_in
= GetType() == TYPE_REGULAR
;
738 bool data_ready
= logged_in
|| GetRemoteDevices() != NULL
;
739 app_manager_
->SendUserUpdatedEvent(user_id
, logged_in
, data_ready
);
742 void EasyUnlockService::NotifyTurnOffOperationStatusChanged() {
744 EasyUnlockServiceObserver
, observers_
, OnTurnOffOperationStatusChanged());
747 void EasyUnlockService::ResetScreenlockState() {
748 screenlock_state_handler_
.reset();
749 auth_attempt_
.reset();
752 void EasyUnlockService::SetScreenlockHardlockedState(
753 EasyUnlockScreenlockStateHandler::HardlockState state
) {
754 if (screenlock_state_handler_
)
755 screenlock_state_handler_
->SetHardlockState(state
);
756 if (state
!= EasyUnlockScreenlockStateHandler::NO_HARDLOCK
)
757 auth_attempt_
.reset();
760 void EasyUnlockService::InitializeOnAppManagerReady() {
761 CHECK(app_manager_
.get());
763 InitializeInternal();
764 bluetooth_detector_
->Initialize();
767 void EasyUnlockService::OnBluetoothAdapterPresentChanged() {
770 // Whether we've already passed Bluetooth availability information to UMA.
771 // This is static because there may be multiple instances and we want to
772 // report this system-level stat only once per run of Chrome.
773 static bool bluetooth_adapter_has_been_reported
= false;
775 if (!bluetooth_adapter_has_been_reported
) {
776 bluetooth_adapter_has_been_reported
= true;
777 int bttype
= BT_NO_ADAPTER
;
778 if (bluetooth_detector_
->IsPresent()) {
779 bttype
= BT_LOW_ENERGY_CAPABLE
;
781 if (base::win::GetVersion() < base::win::VERSION_WIN8
) {
786 UMA_HISTOGRAM_ENUMERATION(
787 "EasyUnlock.BluetoothAvailability", bttype
, BT_MAX_TYPE
);
791 void EasyUnlockService::SetHardlockStateForUser(
792 const std::string
& user_id
,
793 EasyUnlockScreenlockStateHandler::HardlockState state
) {
794 DCHECK(!user_id
.empty());
796 PrefService
* local_state
= GetLocalState();
800 DictionaryPrefUpdate
update(local_state
, prefs::kEasyUnlockHardlockState
);
801 update
->SetIntegerWithoutPathExpansion(user_id
, static_cast<int>(state
));
803 if (GetUserEmail() == user_id
)
804 SetScreenlockHardlockedState(state
);
807 EasyUnlockAuthEvent
EasyUnlockService::GetPasswordAuthEvent() const {
810 if (GetHardlockState() != EasyUnlockScreenlockStateHandler::NO_HARDLOCK
) {
811 switch (GetHardlockState()) {
812 case EasyUnlockScreenlockStateHandler::NO_HARDLOCK
:
814 return EASY_UNLOCK_AUTH_EVENT_COUNT
;
815 case EasyUnlockScreenlockStateHandler::NO_PAIRING
:
816 return PASSWORD_ENTRY_NO_PAIRING
;
817 case EasyUnlockScreenlockStateHandler::USER_HARDLOCK
:
818 return PASSWORD_ENTRY_USER_HARDLOCK
;
819 case EasyUnlockScreenlockStateHandler::PAIRING_CHANGED
:
820 return PASSWORD_ENTRY_PAIRING_CHANGED
;
821 case EasyUnlockScreenlockStateHandler::LOGIN_FAILED
:
822 return PASSWORD_ENTRY_LOGIN_FAILED
;
823 case EasyUnlockScreenlockStateHandler::PAIRING_ADDED
:
824 return PASSWORD_ENTRY_PAIRING_ADDED
;
826 } else if (!screenlock_state_handler()) {
827 return PASSWORD_ENTRY_NO_SCREENLOCK_STATE_HANDLER
;
829 switch (screenlock_state_handler()->state()) {
830 case ScreenlockState::INACTIVE
:
831 return PASSWORD_ENTRY_SERVICE_NOT_ACTIVE
;
832 case ScreenlockState::NO_BLUETOOTH
:
833 return PASSWORD_ENTRY_NO_BLUETOOTH
;
834 case ScreenlockState::BLUETOOTH_CONNECTING
:
835 return PASSWORD_ENTRY_BLUETOOTH_CONNECTING
;
836 case ScreenlockState::NO_PHONE
:
837 return PASSWORD_ENTRY_NO_PHONE
;
838 case ScreenlockState::PHONE_NOT_AUTHENTICATED
:
839 return PASSWORD_ENTRY_PHONE_NOT_AUTHENTICATED
;
840 case ScreenlockState::PHONE_LOCKED
:
841 return PASSWORD_ENTRY_PHONE_LOCKED
;
842 case ScreenlockState::PHONE_NOT_LOCKABLE
:
843 return PASSWORD_ENTRY_PHONE_NOT_LOCKABLE
;
844 case ScreenlockState::PHONE_UNSUPPORTED
:
845 return PASSWORD_ENTRY_PHONE_UNSUPPORTED
;
846 case ScreenlockState::RSSI_TOO_LOW
:
847 return PASSWORD_ENTRY_RSSI_TOO_LOW
;
848 case ScreenlockState::TX_POWER_TOO_HIGH
:
849 return PASSWORD_ENTRY_TX_POWER_TOO_HIGH
;
850 case ScreenlockState::PHONE_LOCKED_AND_TX_POWER_TOO_HIGH
:
851 return PASSWORD_ENTRY_PHONE_LOCKED_AND_TX_POWER_TOO_HIGH
;
852 case ScreenlockState::AUTHENTICATED
:
853 return PASSWORD_ENTRY_WITH_AUTHENTICATED_PHONE
;
858 return EASY_UNLOCK_AUTH_EVENT_COUNT
;
861 #if defined(OS_CHROMEOS)
862 void EasyUnlockService::OnCryptohomeKeysFetchedForChecking(
863 const std::string
& user_id
,
864 const std::set
<std::string
> paired_devices
,
866 const chromeos::EasyUnlockDeviceKeyDataList
& key_data_list
) {
867 DCHECK(!user_id
.empty() && !paired_devices
.empty());
870 SetHardlockStateForUser(user_id
,
871 EasyUnlockScreenlockStateHandler::NO_PAIRING
);
875 std::set
<std::string
> devices_in_cryptohome
;
876 for (const auto& device_key_data
: key_data_list
)
877 devices_in_cryptohome
.insert(device_key_data
.psk
);
879 if (paired_devices
!= devices_in_cryptohome
||
880 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING
) {
881 SetHardlockStateForUser(
883 devices_in_cryptohome
.empty()
884 ? EasyUnlockScreenlockStateHandler::PAIRING_ADDED
885 : EasyUnlockScreenlockStateHandler::PAIRING_CHANGED
);
890 void EasyUnlockService::PrepareForSuspend() {
891 app_manager_
->DisableAppIfLoaded();
892 if (screenlock_state_handler_
&& screenlock_state_handler_
->IsActive())
893 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING
);
896 void EasyUnlockService::EnsureTpmKeyPresentIfNeeded() {
897 if (tpm_key_checked_
|| GetType() != TYPE_REGULAR
|| GetUserEmail().empty() ||
898 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING
) {
902 #if defined(OS_CHROMEOS)
903 // If this is called before the session is started, the chances are Chrome
904 // is restarting in order to apply user flags. Don't check TPM keys in this
906 if (!user_manager::UserManager::Get() ||
907 !user_manager::UserManager::Get()->IsSessionStarted())
910 // TODO(tbarzic): Set check_private_key only if previous sign-in attempt
912 EasyUnlockTpmKeyManagerFactory::GetInstance()->Get(profile_
)
913 ->PrepareTpmKey(true /* check_private_key */,
915 #endif // defined(OS_CHROMEOS)
917 tpm_key_checked_
= true;