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/services/gcm/gcm_profile_service.h"
25 #include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
26 #include "chrome/browser/signin/chrome_proximity_auth_client.h"
27 #include "chrome/browser/signin/easy_unlock_app_manager.h"
28 #include "chrome/browser/signin/easy_unlock_service_factory.h"
29 #include "chrome/browser/signin/easy_unlock_service_observer.h"
30 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
31 #include "chrome/browser/signin/signin_manager_factory.h"
32 #include "chrome/common/chrome_switches.h"
33 #include "chrome/common/extensions/extension_constants.h"
34 #include "chrome/common/pref_names.h"
35 #include "components/pref_registry/pref_registry_syncable.h"
36 #include "components/proximity_auth/ble/proximity_auth_ble_system.h"
37 #include "components/proximity_auth/cryptauth/cryptauth_client_impl.h"
38 #include "components/proximity_auth/cryptauth/cryptauth_device_manager.h"
39 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h"
40 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
41 #include "components/proximity_auth/screenlock_bridge.h"
42 #include "components/proximity_auth/switches.h"
43 #include "components/signin/core/browser/profile_oauth2_token_service.h"
44 #include "components/signin/core/browser/signin_manager.h"
45 #include "components/user_manager/user.h"
46 #include "components/version_info/version_info.h"
47 #include "device/bluetooth/bluetooth_adapter.h"
48 #include "device/bluetooth/bluetooth_adapter_factory.h"
50 #if defined(OS_CHROMEOS)
51 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
52 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
53 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
54 #include "chrome/browser/chromeos/login/easy_unlock/secure_message_delegate_chromeos.h"
55 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
56 #include "chrome/browser/chromeos/profiles/profile_helper.h"
57 #include "chromeos/dbus/dbus_thread_manager.h"
58 #include "chromeos/dbus/power_manager_client.h"
59 #include "components/user_manager/user_manager.h"
63 #include "base/win/windows_version.h"
66 using proximity_auth::ScreenlockState
;
73 BT_LOW_ENERGY_CAPABLE
,
77 PrefService
* GetLocalState() {
78 return g_browser_process
? g_browser_process
->local_state() : NULL
;
83 EasyUnlockService::UserSettings::UserSettings()
84 : require_close_proximity(false) {
87 EasyUnlockService::UserSettings::~UserSettings() {
91 EasyUnlockService
* EasyUnlockService::Get(Profile
* profile
) {
92 return EasyUnlockServiceFactory::GetForBrowserContext(profile
);
96 EasyUnlockService
* EasyUnlockService::GetForUser(
97 const user_manager::User
& user
) {
98 #if defined(OS_CHROMEOS)
99 Profile
* profile
= chromeos::ProfileHelper::Get()->GetProfileByUser(&user
);
102 return EasyUnlockService::Get(profile
);
109 bool EasyUnlockService::IsSignInEnabled() {
110 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
111 proximity_auth::switches::kDisableEasyUnlock
);
114 class EasyUnlockService::BluetoothDetector
115 : public device::BluetoothAdapter::Observer
,
116 public apps::AppLifetimeMonitor::Observer
{
118 explicit BluetoothDetector(EasyUnlockService
* service
)
120 weak_ptr_factory_(this) {
121 apps::AppLifetimeMonitorFactory::GetForProfile(service_
->profile())
125 ~BluetoothDetector() override
{
127 adapter_
->RemoveObserver(this);
128 apps::AppLifetimeMonitorFactory::GetForProfile(service_
->profile())
129 ->RemoveObserver(this);
133 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
136 device::BluetoothAdapterFactory::GetAdapter(
137 base::Bind(&BluetoothDetector::OnAdapterInitialized
,
138 weak_ptr_factory_
.GetWeakPtr()));
141 bool IsPresent() const { return adapter_
.get() && adapter_
->IsPresent(); }
143 // device::BluetoothAdapter::Observer:
144 void AdapterPresentChanged(device::BluetoothAdapter
* adapter
,
145 bool present
) override
{
146 service_
->OnBluetoothAdapterPresentChanged();
149 device::BluetoothAdapter
* getAdapter() {
150 return adapter_
.get();
154 void OnAdapterInitialized(scoped_refptr
<device::BluetoothAdapter
> adapter
) {
156 adapter_
->AddObserver(this);
157 service_
->OnBluetoothAdapterPresentChanged();
159 #if !defined(OS_CHROMEOS)
160 // Bluetooth detection causes serious performance degradations on Mac
161 // and possibly other platforms as well: http://crbug.com/467316
162 // Since this feature is currently only offered for ChromeOS we just
163 // turn it off on other platforms once the inforamtion about the
164 // adapter has been gathered and reported.
165 // TODO(bcwhite,xiyuan): Revisit when non-chromeos platforms are supported.
166 adapter_
->RemoveObserver(this);
169 // TODO(tengs): At the moment, there is no way for Bluetooth discoverability
170 // to be turned on except through the Easy Unlock setup. If we step on any
171 // toes in the future then we need to revisit this guard.
172 if (adapter_
->IsDiscoverable())
173 TurnOffBluetoothDiscoverability();
174 #endif // !defined(OS_CHROMEOS)
177 // apps::AppLifetimeMonitor::Observer:
178 void OnAppDeactivated(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 OnAppStop(Profile
* profile
, const std::string
& app_id
) override
{
185 // TODO(tengs): Refactor the lifetime management to EasyUnlockAppManager.
186 if (app_id
== extension_misc::kEasyUnlockAppId
)
187 TurnOffBluetoothDiscoverability();
190 void TurnOffBluetoothDiscoverability() {
192 adapter_
->SetDiscoverable(
193 false, base::Bind(&base::DoNothing
), base::Bind(&base::DoNothing
));
197 // Owner of this class and should out-live this class.
198 EasyUnlockService
* service_
;
199 scoped_refptr
<device::BluetoothAdapter
> adapter_
;
200 base::WeakPtrFactory
<BluetoothDetector
> weak_ptr_factory_
;
202 DISALLOW_COPY_AND_ASSIGN(BluetoothDetector
);
205 #if defined(OS_CHROMEOS)
206 class EasyUnlockService::PowerMonitor
207 : public chromeos::PowerManagerClient::Observer
{
209 explicit PowerMonitor(EasyUnlockService
* service
)
212 weak_ptr_factory_(this) {
213 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
217 ~PowerMonitor() override
{
218 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
219 RemoveObserver(this);
222 // Called when the remote device has been authenticated to record the time
223 // delta from waking up. No time will be recorded if the start-up time has
224 // already been recorded or if the system never went to sleep previously.
225 void RecordStartUpTime() {
226 if (wake_up_time_
.is_null())
228 UMA_HISTOGRAM_MEDIUM_TIMES(
229 "EasyUnlock.StartupTimeFromSuspend",
230 base::Time::Now() - wake_up_time_
);
231 wake_up_time_
= base::Time();
234 bool waking_up() const { return waking_up_
; }
237 // chromeos::PowerManagerClient::Observer:
238 void SuspendImminent() override
{ service_
->PrepareForSuspend(); }
240 void SuspendDone(const base::TimeDelta
& sleep_duration
) override
{
242 wake_up_time_
= base::Time::Now();
243 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
245 base::Bind(&PowerMonitor::ResetWakingUp
,
246 weak_ptr_factory_
.GetWeakPtr()),
247 base::TimeDelta::FromSeconds(5));
248 service_
->OnSuspendDone();
249 service_
->UpdateAppState();
250 // Note that |this| may get deleted after |UpdateAppState| is called.
253 void ResetWakingUp() {
255 service_
->UpdateAppState();
258 EasyUnlockService
* service_
;
260 base::Time wake_up_time_
;
261 base::WeakPtrFactory
<PowerMonitor
> weak_ptr_factory_
;
263 DISALLOW_COPY_AND_ASSIGN(PowerMonitor
);
267 EasyUnlockService::EasyUnlockService(Profile
* profile
)
269 proximity_auth_client_(profile
),
270 bluetooth_detector_(new BluetoothDetector(this)),
272 tpm_key_checked_(false),
273 weak_ptr_factory_(this) {
276 EasyUnlockService::~EasyUnlockService() {
280 void EasyUnlockService::RegisterProfilePrefs(
281 user_prefs::PrefRegistrySyncable
* registry
) {
282 registry
->RegisterBooleanPref(prefs::kEasyUnlockAllowed
, true);
283 registry
->RegisterBooleanPref(prefs::kEasyUnlockEnabled
, false);
284 registry
->RegisterDictionaryPref(prefs::kEasyUnlockPairing
,
285 new base::DictionaryValue());
286 registry
->RegisterBooleanPref(
287 prefs::kEasyUnlockProximityRequired
,
289 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
291 proximity_auth::CryptAuthGCMManager::RegisterPrefs(registry
);
292 proximity_auth::CryptAuthDeviceManager::RegisterPrefs(registry
);
293 proximity_auth::CryptAuthEnrollmentManager::RegisterPrefs(registry
);
295 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
296 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery
))
297 proximity_auth::ProximityAuthBleSystem::RegisterPrefs(registry
);
301 void EasyUnlockService::RegisterPrefs(PrefRegistrySimple
* registry
) {
302 registry
->RegisterStringPref(prefs::kEasyUnlockDeviceId
, std::string());
303 registry
->RegisterDictionaryPref(prefs::kEasyUnlockHardlockState
);
304 registry
->RegisterDictionaryPref(prefs::kEasyUnlockLocalStateUserPrefs
);
305 #if defined(OS_CHROMEOS)
306 EasyUnlockTpmKeyManager::RegisterLocalStatePrefs(registry
);
311 void EasyUnlockService::ResetLocalStateForUser(const std::string
& user_id
) {
312 DCHECK(!user_id
.empty());
314 PrefService
* local_state
= GetLocalState();
318 DictionaryPrefUpdate
update(local_state
, prefs::kEasyUnlockHardlockState
);
319 update
->RemoveWithoutPathExpansion(user_id
, NULL
);
321 #if defined(OS_CHROMEOS)
322 EasyUnlockTpmKeyManager::ResetLocalStateForUser(user_id
);
327 EasyUnlockService::UserSettings
EasyUnlockService::GetUserSettings(
328 const std::string
& user_id
) {
329 DCHECK(!user_id
.empty());
330 UserSettings user_settings
;
332 PrefService
* local_state
= GetLocalState();
334 return user_settings
;
336 const base::DictionaryValue
* all_user_prefs_dict
=
337 local_state
->GetDictionary(prefs::kEasyUnlockLocalStateUserPrefs
);
338 if (!all_user_prefs_dict
)
339 return user_settings
;
341 const base::DictionaryValue
* user_prefs_dict
;
342 if (!all_user_prefs_dict
->GetDictionaryWithoutPathExpansion(user_id
,
344 return user_settings
;
346 user_prefs_dict
->GetBooleanWithoutPathExpansion(
347 prefs::kEasyUnlockProximityRequired
,
348 &user_settings
.require_close_proximity
);
350 return user_settings
;
354 std::string
EasyUnlockService::GetDeviceId() {
355 PrefService
* local_state
= GetLocalState();
357 return std::string();
359 std::string device_id
= local_state
->GetString(prefs::kEasyUnlockDeviceId
);
360 if (device_id
.empty()) {
361 device_id
= base::GenerateGUID();
362 local_state
->SetString(prefs::kEasyUnlockDeviceId
, device_id
);
367 void EasyUnlockService::Initialize(
368 scoped_ptr
<EasyUnlockAppManager
> app_manager
) {
369 app_manager_
= app_manager
.Pass();
370 app_manager_
->EnsureReady(
371 base::Bind(&EasyUnlockService::InitializeOnAppManagerReady
,
372 weak_ptr_factory_
.GetWeakPtr()));
375 bool EasyUnlockService::IsAllowed() const {
379 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
380 proximity_auth::switches::kDisableEasyUnlock
)) {
384 if (!IsAllowedInternal())
387 #if defined(OS_CHROMEOS)
388 if (!bluetooth_detector_
->IsPresent())
393 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
398 bool EasyUnlockService::IsEnabled() const {
399 // The feature is enabled iff there are any paired devices.
400 const base::ListValue
* devices
= GetRemoteDevices();
401 return devices
&& !devices
->empty();
404 void EasyUnlockService::OpenSetupApp() {
405 app_manager_
->LaunchSetup();
408 void EasyUnlockService::SetHardlockState(
409 EasyUnlockScreenlockStateHandler::HardlockState state
) {
410 const std::string user_id
= GetUserEmail();
414 if (state
== GetHardlockState())
417 SetHardlockStateForUser(user_id
, state
);
420 EasyUnlockScreenlockStateHandler::HardlockState
421 EasyUnlockService::GetHardlockState() const {
422 EasyUnlockScreenlockStateHandler::HardlockState state
;
423 if (GetPersistedHardlockState(&state
))
426 return EasyUnlockScreenlockStateHandler::NO_HARDLOCK
;
429 bool EasyUnlockService::GetPersistedHardlockState(
430 EasyUnlockScreenlockStateHandler::HardlockState
* state
) const {
431 std::string user_id
= GetUserEmail();
435 PrefService
* local_state
= GetLocalState();
439 const base::DictionaryValue
* dict
=
440 local_state
->GetDictionary(prefs::kEasyUnlockHardlockState
);
442 if (dict
&& dict
->GetIntegerWithoutPathExpansion(user_id
, &state_int
)) {
444 static_cast<EasyUnlockScreenlockStateHandler::HardlockState
>(state_int
);
451 void EasyUnlockService::ShowInitialUserState() {
452 if (!GetScreenlockStateHandler())
455 EasyUnlockScreenlockStateHandler::HardlockState state
;
456 bool has_persisted_state
= GetPersistedHardlockState(&state
);
457 if (!has_persisted_state
)
460 if (state
== EasyUnlockScreenlockStateHandler::NO_HARDLOCK
) {
461 // Show connecting icon early when there is a persisted non hardlock state.
462 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING
);
464 screenlock_state_handler_
->MaybeShowHardlockUI();
468 EasyUnlockScreenlockStateHandler
*
469 EasyUnlockService::GetScreenlockStateHandler() {
472 if (!screenlock_state_handler_
) {
473 screenlock_state_handler_
.reset(new EasyUnlockScreenlockStateHandler(
474 GetUserEmail(), GetHardlockState(),
475 proximity_auth::ScreenlockBridge::Get()));
477 return screenlock_state_handler_
.get();
480 bool EasyUnlockService::UpdateScreenlockState(ScreenlockState state
) {
481 EasyUnlockScreenlockStateHandler
* handler
= GetScreenlockStateHandler();
485 handler
->ChangeState(state
);
487 if (state
== ScreenlockState::AUTHENTICATED
) {
488 #if defined(OS_CHROMEOS)
490 power_monitor_
->RecordStartUpTime();
492 } else if (auth_attempt_
.get()) {
493 // Clean up existing auth attempt if we can no longer authenticate the
495 auth_attempt_
.reset();
497 if (!handler
->InStateValidOnRemoteAuthFailure())
498 HandleAuthFailure(GetUserEmail());
502 EasyUnlockServiceObserver
, observers_
, OnScreenlockStateChanged(state
));
506 ScreenlockState
EasyUnlockService::GetScreenlockState() {
507 EasyUnlockScreenlockStateHandler
* handler
= GetScreenlockStateHandler();
509 return ScreenlockState::INACTIVE
;
511 return handler
->state();
514 void EasyUnlockService::AttemptAuth(const std::string
& user_id
) {
515 AttemptAuth(user_id
, AttemptAuthCallback());
518 void EasyUnlockService::AttemptAuth(const std::string
& user_id
,
519 const AttemptAuthCallback
& callback
) {
520 const EasyUnlockAuthAttempt::Type auth_attempt_type
=
521 GetType() == TYPE_REGULAR
? EasyUnlockAuthAttempt::TYPE_UNLOCK
522 : EasyUnlockAuthAttempt::TYPE_SIGNIN
;
523 const std::string user_email
= GetUserEmail();
524 if (user_email
.empty()) {
525 LOG(ERROR
) << "Empty user email. Refresh token might go bad.";
526 if (!callback
.is_null()) {
527 const bool kFailure
= false;
528 callback
.Run(auth_attempt_type
, kFailure
, user_id
, std::string(),
534 CHECK_EQ(GetUserEmail(), user_id
);
536 auth_attempt_
.reset(new EasyUnlockAuthAttempt(app_manager_
.get(), user_id
,
537 auth_attempt_type
, callback
));
538 if (!auth_attempt_
->Start())
539 auth_attempt_
.reset();
541 // TODO(tengs): We notify ProximityAuthBleSystem whenever unlock attempts are
542 // attempted. However, we ideally should refactor the auth attempt logic to
543 // the proximity_auth component.
544 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
545 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery
) &&
546 auth_attempt_type
== EasyUnlockAuthAttempt::TYPE_UNLOCK
&&
547 proximity_auth_ble_system_
) {
548 proximity_auth_ble_system_
->OnAuthAttempted(user_id
);
552 void EasyUnlockService::FinalizeUnlock(bool success
) {
553 if (!auth_attempt_
.get())
556 this->OnWillFinalizeUnlock(success
);
557 auth_attempt_
->FinalizeUnlock(GetUserEmail(), success
);
558 auth_attempt_
.reset();
559 // TODO(isherman): If observing screen unlock events, is there a race
560 // condition in terms of reading the service's state vs. the app setting the
563 // Make sure that the lock screen is updated on failure.
565 RecordEasyUnlockScreenUnlockEvent(EASY_UNLOCK_FAILURE
);
566 HandleAuthFailure(GetUserEmail());
570 void EasyUnlockService::FinalizeSignin(const std::string
& key
) {
571 if (!auth_attempt_
.get())
573 std::string wrapped_secret
= GetWrappedSecret();
574 if (!wrapped_secret
.empty())
575 auth_attempt_
->FinalizeSignin(GetUserEmail(), wrapped_secret
, key
);
576 auth_attempt_
.reset();
578 // Processing empty key is equivalent to auth cancellation. In this case the
579 // signin request will not actually be processed by login stack, so the lock
580 // screen state should be set from here.
582 HandleAuthFailure(GetUserEmail());
585 void EasyUnlockService::HandleAuthFailure(const std::string
& user_id
) {
586 if (user_id
!= GetUserEmail())
589 if (!screenlock_state_handler_
.get())
592 screenlock_state_handler_
->SetHardlockState(
593 EasyUnlockScreenlockStateHandler::LOGIN_FAILED
);
596 void EasyUnlockService::CheckCryptohomeKeysAndMaybeHardlock() {
597 #if defined(OS_CHROMEOS)
598 std::string user_id
= GetUserEmail();
602 const base::ListValue
* device_list
= GetRemoteDevices();
603 std::set
<std::string
> paired_devices
;
605 chromeos::EasyUnlockDeviceKeyDataList parsed_paired
;
606 chromeos::EasyUnlockKeyManager::RemoteDeviceListToDeviceDataList(
607 *device_list
, &parsed_paired
);
608 for (const auto& device_key_data
: parsed_paired
)
609 paired_devices
.insert(device_key_data
.psk
);
611 if (paired_devices
.empty()) {
612 SetHardlockState(EasyUnlockScreenlockStateHandler::NO_PAIRING
);
616 // No need to compare if a change is already recorded.
617 if (GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_CHANGED
||
618 GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_ADDED
) {
622 chromeos::EasyUnlockKeyManager
* key_manager
=
623 chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager();
626 key_manager
->GetDeviceDataList(
627 chromeos::UserContext(user_id
),
628 base::Bind(&EasyUnlockService::OnCryptohomeKeysFetchedForChecking
,
629 weak_ptr_factory_
.GetWeakPtr(),
635 void EasyUnlockService::SetTrialRun() {
636 DCHECK_EQ(GetType(), TYPE_REGULAR
);
638 EasyUnlockScreenlockStateHandler
* handler
= GetScreenlockStateHandler();
640 handler
->SetTrialRun();
643 void EasyUnlockService::RecordClickOnLockIcon() {
644 if (screenlock_state_handler_
)
645 screenlock_state_handler_
->RecordClickOnLockIcon();
648 void EasyUnlockService::AddObserver(EasyUnlockServiceObserver
* observer
) {
649 observers_
.AddObserver(observer
);
652 void EasyUnlockService::RemoveObserver(EasyUnlockServiceObserver
* observer
) {
653 observers_
.RemoveObserver(observer
);
656 PrefService
* EasyUnlockService::GetPrefService() {
657 return profile()->GetPrefs();
660 scoped_ptr
<proximity_auth::SecureMessageDelegate
>
661 EasyUnlockService::CreateSecureMessageDelegate() {
662 #if defined(OS_CHROMEOS)
663 return make_scoped_ptr(new chromeos::SecureMessageDelegateChromeOS());
669 scoped_ptr
<proximity_auth::CryptAuthClientFactory
>
670 EasyUnlockService::CreateCryptAuthClientFactory() {
671 return make_scoped_ptr(new proximity_auth::CryptAuthClientFactoryImpl(
672 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()),
673 SigninManagerFactory::GetForProfile(profile())
674 ->GetAuthenticatedAccountId(),
675 profile()->GetRequestContext(), GetDeviceClassifier()));
678 cryptauth::DeviceClassifier
EasyUnlockService::GetDeviceClassifier() {
679 cryptauth::DeviceClassifier device_classifier
;
681 #if defined(OS_CHROMEOS)
682 int32 major_version
, minor_version
, bugfix_version
;
683 // TODO(tengs): base::OperatingSystemVersionNumbers only works for ChromeOS.
684 // We need to get different numbers for other platforms.
685 base::SysInfo::OperatingSystemVersionNumbers(&major_version
, &minor_version
,
687 device_classifier
.set_device_os_version_code(major_version
);
688 device_classifier
.set_device_type(cryptauth::CHROME
);
691 const std::vector
<uint32_t>& version_components
=
692 base::Version(version_info::GetVersionNumber()).components();
693 if (version_components
.size() > 0)
694 device_classifier
.set_device_software_version_code(version_components
[0]);
696 device_classifier
.set_device_software_package(version_info::GetProductName());
697 return device_classifier
;
700 std::string
EasyUnlockService::GetAccountId() {
701 return SigninManagerFactory::GetForProfile(profile())
702 ->GetAuthenticatedAccountId();
705 gcm::GCMDriver
* EasyUnlockService::GetGCMDriver() {
706 gcm::GCMProfileService
* gcm_profile_service
=
707 gcm::GCMProfileServiceFactory::GetForProfile(profile_
);
708 return gcm_profile_service
->driver();
711 void EasyUnlockService::Shutdown() {
718 ResetScreenlockState();
719 bluetooth_detector_
.reset();
720 #if defined(OS_CHROMEOS)
721 power_monitor_
.reset();
724 weak_ptr_factory_
.InvalidateWeakPtrs();
727 void EasyUnlockService::ReloadAppAndLockScreen() {
728 // Make sure lock screen state set by the extension gets reset.
729 ResetScreenlockState();
730 app_manager_
->ReloadApp();
734 void EasyUnlockService::UpdateAppState() {
736 EnsureTpmKeyPresentIfNeeded();
737 app_manager_
->LoadApp();
740 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
741 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery
) &&
742 GetType() == EasyUnlockService::TYPE_REGULAR
&&
743 !proximity_auth_ble_system_
) {
744 proximity_auth_ble_system_
.reset(
745 new proximity_auth::ProximityAuthBleSystem(
746 proximity_auth::ScreenlockBridge::Get(), &proximity_auth_client_
,
747 CreateCryptAuthClientFactory(), profile_
->GetPrefs()));
750 #if defined(OS_CHROMEOS)
752 power_monitor_
.reset(new PowerMonitor(this));
755 bool bluetooth_waking_up
= false;
756 #if defined(OS_CHROMEOS)
757 // If the service is not allowed due to bluetooth not being detected just
758 // after system suspend is done, give bluetooth more time to be detected
759 // before disabling the app (and resetting screenlock state).
760 bluetooth_waking_up
=
761 power_monitor_
.get() && power_monitor_
->waking_up() &&
762 !bluetooth_detector_
->IsPresent();
765 if (!bluetooth_waking_up
) {
766 app_manager_
->DisableAppIfLoaded();
767 ResetScreenlockState();
768 proximity_auth_ble_system_
.reset();
769 #if defined(OS_CHROMEOS)
770 power_monitor_
.reset();
776 void EasyUnlockService::DisableAppWithoutResettingScreenlockState() {
777 app_manager_
->DisableAppIfLoaded();
780 void EasyUnlockService::NotifyUserUpdated() {
781 std::string user_id
= GetUserEmail();
785 // Notify the easy unlock app that the user info changed.
786 bool logged_in
= GetType() == TYPE_REGULAR
;
787 bool data_ready
= logged_in
|| GetRemoteDevices() != NULL
;
788 app_manager_
->SendUserUpdatedEvent(user_id
, logged_in
, data_ready
);
791 void EasyUnlockService::NotifyTurnOffOperationStatusChanged() {
793 EasyUnlockServiceObserver
, observers_
, OnTurnOffOperationStatusChanged());
796 void EasyUnlockService::ResetScreenlockState() {
797 screenlock_state_handler_
.reset();
798 auth_attempt_
.reset();
801 void EasyUnlockService::SetScreenlockHardlockedState(
802 EasyUnlockScreenlockStateHandler::HardlockState state
) {
803 if (screenlock_state_handler_
)
804 screenlock_state_handler_
->SetHardlockState(state
);
805 if (state
!= EasyUnlockScreenlockStateHandler::NO_HARDLOCK
)
806 auth_attempt_
.reset();
809 void EasyUnlockService::InitializeOnAppManagerReady() {
810 CHECK(app_manager_
.get());
812 InitializeInternal();
813 bluetooth_detector_
->Initialize();
816 void EasyUnlockService::OnBluetoothAdapterPresentChanged() {
819 // Whether we've already passed Bluetooth availability information to UMA.
820 // This is static because there may be multiple instances and we want to
821 // report this system-level stat only once per run of Chrome.
822 static bool bluetooth_adapter_has_been_reported
= false;
824 if (!bluetooth_adapter_has_been_reported
) {
825 bluetooth_adapter_has_been_reported
= true;
826 int bttype
= BT_NO_ADAPTER
;
827 if (bluetooth_detector_
->IsPresent()) {
828 bttype
= BT_LOW_ENERGY_CAPABLE
;
830 if (base::win::GetVersion() < base::win::VERSION_WIN8
) {
835 UMA_HISTOGRAM_ENUMERATION(
836 "EasyUnlock.BluetoothAvailability", bttype
, BT_MAX_TYPE
);
840 void EasyUnlockService::SetHardlockStateForUser(
841 const std::string
& user_id
,
842 EasyUnlockScreenlockStateHandler::HardlockState state
) {
843 DCHECK(!user_id
.empty());
845 PrefService
* local_state
= GetLocalState();
849 DictionaryPrefUpdate
update(local_state
, prefs::kEasyUnlockHardlockState
);
850 update
->SetIntegerWithoutPathExpansion(user_id
, static_cast<int>(state
));
852 if (GetUserEmail() == user_id
)
853 SetScreenlockHardlockedState(state
);
856 EasyUnlockAuthEvent
EasyUnlockService::GetPasswordAuthEvent() const {
859 if (GetHardlockState() != EasyUnlockScreenlockStateHandler::NO_HARDLOCK
) {
860 switch (GetHardlockState()) {
861 case EasyUnlockScreenlockStateHandler::NO_HARDLOCK
:
863 return EASY_UNLOCK_AUTH_EVENT_COUNT
;
864 case EasyUnlockScreenlockStateHandler::NO_PAIRING
:
865 return PASSWORD_ENTRY_NO_PAIRING
;
866 case EasyUnlockScreenlockStateHandler::USER_HARDLOCK
:
867 return PASSWORD_ENTRY_USER_HARDLOCK
;
868 case EasyUnlockScreenlockStateHandler::PAIRING_CHANGED
:
869 return PASSWORD_ENTRY_PAIRING_CHANGED
;
870 case EasyUnlockScreenlockStateHandler::LOGIN_FAILED
:
871 return PASSWORD_ENTRY_LOGIN_FAILED
;
872 case EasyUnlockScreenlockStateHandler::PAIRING_ADDED
:
873 return PASSWORD_ENTRY_PAIRING_ADDED
;
875 } else if (!screenlock_state_handler()) {
876 return PASSWORD_ENTRY_NO_SCREENLOCK_STATE_HANDLER
;
878 switch (screenlock_state_handler()->state()) {
879 case ScreenlockState::INACTIVE
:
880 return PASSWORD_ENTRY_SERVICE_NOT_ACTIVE
;
881 case ScreenlockState::NO_BLUETOOTH
:
882 return PASSWORD_ENTRY_NO_BLUETOOTH
;
883 case ScreenlockState::BLUETOOTH_CONNECTING
:
884 return PASSWORD_ENTRY_BLUETOOTH_CONNECTING
;
885 case ScreenlockState::NO_PHONE
:
886 return PASSWORD_ENTRY_NO_PHONE
;
887 case ScreenlockState::PHONE_NOT_AUTHENTICATED
:
888 return PASSWORD_ENTRY_PHONE_NOT_AUTHENTICATED
;
889 case ScreenlockState::PHONE_LOCKED
:
890 return PASSWORD_ENTRY_PHONE_LOCKED
;
891 case ScreenlockState::PHONE_NOT_LOCKABLE
:
892 return PASSWORD_ENTRY_PHONE_NOT_LOCKABLE
;
893 case ScreenlockState::PHONE_UNSUPPORTED
:
894 return PASSWORD_ENTRY_PHONE_UNSUPPORTED
;
895 case ScreenlockState::RSSI_TOO_LOW
:
896 return PASSWORD_ENTRY_RSSI_TOO_LOW
;
897 case ScreenlockState::TX_POWER_TOO_HIGH
:
898 return PASSWORD_ENTRY_TX_POWER_TOO_HIGH
;
899 case ScreenlockState::PHONE_LOCKED_AND_TX_POWER_TOO_HIGH
:
900 return PASSWORD_ENTRY_PHONE_LOCKED_AND_TX_POWER_TOO_HIGH
;
901 case ScreenlockState::AUTHENTICATED
:
902 return PASSWORD_ENTRY_WITH_AUTHENTICATED_PHONE
;
907 return EASY_UNLOCK_AUTH_EVENT_COUNT
;
910 #if defined(OS_CHROMEOS)
911 void EasyUnlockService::OnCryptohomeKeysFetchedForChecking(
912 const std::string
& user_id
,
913 const std::set
<std::string
> paired_devices
,
915 const chromeos::EasyUnlockDeviceKeyDataList
& key_data_list
) {
916 DCHECK(!user_id
.empty() && !paired_devices
.empty());
919 SetHardlockStateForUser(user_id
,
920 EasyUnlockScreenlockStateHandler::NO_PAIRING
);
924 std::set
<std::string
> devices_in_cryptohome
;
925 for (const auto& device_key_data
: key_data_list
)
926 devices_in_cryptohome
.insert(device_key_data
.psk
);
928 if (paired_devices
!= devices_in_cryptohome
||
929 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING
) {
930 SetHardlockStateForUser(
932 devices_in_cryptohome
.empty()
933 ? EasyUnlockScreenlockStateHandler::PAIRING_ADDED
934 : EasyUnlockScreenlockStateHandler::PAIRING_CHANGED
);
939 void EasyUnlockService::PrepareForSuspend() {
940 app_manager_
->DisableAppIfLoaded();
941 if (screenlock_state_handler_
&& screenlock_state_handler_
->IsActive())
942 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING
);
945 void EasyUnlockService::EnsureTpmKeyPresentIfNeeded() {
946 if (tpm_key_checked_
|| GetType() != TYPE_REGULAR
|| GetUserEmail().empty() ||
947 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING
) {
951 #if defined(OS_CHROMEOS)
952 // If this is called before the session is started, the chances are Chrome
953 // is restarting in order to apply user flags. Don't check TPM keys in this
955 if (!user_manager::UserManager::Get() ||
956 !user_manager::UserManager::Get()->IsSessionStarted())
959 // TODO(tbarzic): Set check_private_key only if previous sign-in attempt
961 EasyUnlockTpmKeyManagerFactory::GetInstance()->Get(profile_
)
962 ->PrepareTpmKey(true /* check_private_key */,
964 #endif // defined(OS_CHROMEOS)
966 tpm_key_checked_
= true;