[Proximity Auth] Remove the ProximityAuthFacade class.
[chromium-blink-merge.git] / chrome / browser / signin / easy_unlock_service.cc
blob6236dfe813c09df15ecaf5b36e4ef81bd090fbb2
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"
9 #include "base/bind.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/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"
54 #endif
56 #if defined(OS_WIN)
57 #include "base/win/windows_version.h"
58 #endif
60 using proximity_auth::ScreenlockState;
62 namespace {
64 enum BluetoothType {
65 BT_NO_ADAPTER,
66 BT_NORMAL,
67 BT_LOW_ENERGY_CAPABLE,
68 BT_MAX_TYPE
71 PrefService* GetLocalState() {
72 return g_browser_process ? g_browser_process->local_state() : NULL;
75 } // namespace
77 EasyUnlockService::UserSettings::UserSettings()
78 : require_close_proximity(false) {
81 EasyUnlockService::UserSettings::~UserSettings() {
84 // static
85 EasyUnlockService* EasyUnlockService::Get(Profile* profile) {
86 return EasyUnlockServiceFactory::GetForBrowserContext(profile);
89 // static
90 EasyUnlockService* EasyUnlockService::GetForUser(
91 const user_manager::User& user) {
92 #if defined(OS_CHROMEOS)
93 Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(&user);
94 if (!profile)
95 return NULL;
96 return EasyUnlockService::Get(profile);
97 #else
98 return NULL;
99 #endif
102 // static
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 {
111 public:
112 explicit BluetoothDetector(EasyUnlockService* service)
113 : service_(service),
114 weak_ptr_factory_(this) {
115 apps::AppLifetimeMonitorFactory::GetForProfile(service_->profile())
116 ->AddObserver(this);
119 ~BluetoothDetector() override {
120 if (adapter_.get())
121 adapter_->RemoveObserver(this);
122 apps::AppLifetimeMonitorFactory::GetForProfile(service_->profile())
123 ->RemoveObserver(this);
126 void Initialize() {
127 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
128 return;
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();
147 private:
148 void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter) {
149 adapter_ = 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);
161 adapter_ = NULL;
162 #else
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() {
185 if (adapter_) {
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 {
202 public:
203 explicit PowerMonitor(EasyUnlockService* service)
204 : service_(service),
205 waking_up_(false),
206 weak_ptr_factory_(this) {
207 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
208 AddObserver(this);
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())
221 return;
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_; }
230 private:
231 // chromeos::PowerManagerClient::Observer:
232 void SuspendImminent() override { service_->PrepareForSuspend(); }
234 void SuspendDone(const base::TimeDelta& sleep_duration) override {
235 waking_up_ = true;
236 wake_up_time_ = base::Time::Now();
237 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
238 FROM_HERE,
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() {
248 waking_up_ = false;
249 service_->UpdateAppState();
252 EasyUnlockService* service_;
253 bool waking_up_;
254 base::Time wake_up_time_;
255 base::WeakPtrFactory<PowerMonitor> weak_ptr_factory_;
257 DISALLOW_COPY_AND_ASSIGN(PowerMonitor);
259 #endif
261 EasyUnlockService::EasyUnlockService(Profile* profile)
262 : profile_(profile),
263 proximity_auth_client_(profile),
264 bluetooth_detector_(new BluetoothDetector(this)),
265 shut_down_(false),
266 tpm_key_checked_(false),
267 weak_ptr_factory_(this) {
270 EasyUnlockService::~EasyUnlockService() {
273 // static
274 void EasyUnlockService::RegisterProfilePrefs(
275 user_prefs::PrefRegistrySyncable* registry) {
276 registry->RegisterBooleanPref(prefs::kEasyUnlockAllowed, true);
277 registry->RegisterBooleanPref(prefs::kEasyUnlockEnabled, false);
278 registry->RegisterDictionaryPref(prefs::kEasyUnlockPairing,
279 new base::DictionaryValue());
280 registry->RegisterBooleanPref(
281 prefs::kEasyUnlockProximityRequired,
282 false,
283 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
286 // static
287 void EasyUnlockService::RegisterPrefs(PrefRegistrySimple* registry) {
288 registry->RegisterStringPref(prefs::kEasyUnlockDeviceId, std::string());
289 registry->RegisterDictionaryPref(prefs::kEasyUnlockHardlockState);
290 registry->RegisterDictionaryPref(prefs::kEasyUnlockLocalStateUserPrefs);
291 #if defined(OS_CHROMEOS)
292 EasyUnlockTpmKeyManager::RegisterLocalStatePrefs(registry);
293 #endif
296 // static
297 void EasyUnlockService::ResetLocalStateForUser(const std::string& user_id) {
298 DCHECK(!user_id.empty());
300 PrefService* local_state = GetLocalState();
301 if (!local_state)
302 return;
304 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
305 update->RemoveWithoutPathExpansion(user_id, NULL);
307 #if defined(OS_CHROMEOS)
308 EasyUnlockTpmKeyManager::ResetLocalStateForUser(user_id);
309 #endif
312 // static
313 EasyUnlockService::UserSettings EasyUnlockService::GetUserSettings(
314 const std::string& user_id) {
315 DCHECK(!user_id.empty());
316 UserSettings user_settings;
318 PrefService* local_state = GetLocalState();
319 if (!local_state)
320 return user_settings;
322 const base::DictionaryValue* all_user_prefs_dict =
323 local_state->GetDictionary(prefs::kEasyUnlockLocalStateUserPrefs);
324 if (!all_user_prefs_dict)
325 return user_settings;
327 const base::DictionaryValue* user_prefs_dict;
328 if (!all_user_prefs_dict->GetDictionaryWithoutPathExpansion(user_id,
329 &user_prefs_dict))
330 return user_settings;
332 user_prefs_dict->GetBooleanWithoutPathExpansion(
333 prefs::kEasyUnlockProximityRequired,
334 &user_settings.require_close_proximity);
336 return user_settings;
339 // static
340 std::string EasyUnlockService::GetDeviceId() {
341 PrefService* local_state = GetLocalState();
342 if (!local_state)
343 return std::string();
345 std::string device_id = local_state->GetString(prefs::kEasyUnlockDeviceId);
346 if (device_id.empty()) {
347 device_id = base::GenerateGUID();
348 local_state->SetString(prefs::kEasyUnlockDeviceId, device_id);
350 return device_id;
353 void EasyUnlockService::Initialize(
354 scoped_ptr<EasyUnlockAppManager> app_manager) {
355 app_manager_ = app_manager.Pass();
356 app_manager_->EnsureReady(
357 base::Bind(&EasyUnlockService::InitializeOnAppManagerReady,
358 weak_ptr_factory_.GetWeakPtr()));
361 bool EasyUnlockService::IsAllowed() const {
362 if (shut_down_)
363 return false;
365 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
366 proximity_auth::switches::kDisableEasyUnlock)) {
367 return false;
370 if (!IsAllowedInternal())
371 return false;
373 #if defined(OS_CHROMEOS)
374 if (!bluetooth_detector_->IsPresent())
375 return false;
377 return true;
378 #else
379 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
380 return false;
381 #endif
384 bool EasyUnlockService::IsEnabled() const {
385 // The feature is enabled iff there are any paired devices.
386 const base::ListValue* devices = GetRemoteDevices();
387 return devices && !devices->empty();
390 void EasyUnlockService::OpenSetupApp() {
391 app_manager_->LaunchSetup();
394 void EasyUnlockService::SetHardlockState(
395 EasyUnlockScreenlockStateHandler::HardlockState state) {
396 const std::string user_id = GetUserEmail();
397 if (user_id.empty())
398 return;
400 if (state == GetHardlockState())
401 return;
403 SetHardlockStateForUser(user_id, state);
406 EasyUnlockScreenlockStateHandler::HardlockState
407 EasyUnlockService::GetHardlockState() const {
408 EasyUnlockScreenlockStateHandler::HardlockState state;
409 if (GetPersistedHardlockState(&state))
410 return state;
412 return EasyUnlockScreenlockStateHandler::NO_HARDLOCK;
415 bool EasyUnlockService::GetPersistedHardlockState(
416 EasyUnlockScreenlockStateHandler::HardlockState* state) const {
417 std::string user_id = GetUserEmail();
418 if (user_id.empty())
419 return false;
421 PrefService* local_state = GetLocalState();
422 if (!local_state)
423 return false;
425 const base::DictionaryValue* dict =
426 local_state->GetDictionary(prefs::kEasyUnlockHardlockState);
427 int state_int;
428 if (dict && dict->GetIntegerWithoutPathExpansion(user_id, &state_int)) {
429 *state =
430 static_cast<EasyUnlockScreenlockStateHandler::HardlockState>(state_int);
431 return true;
434 return false;
437 void EasyUnlockService::ShowInitialUserState() {
438 if (!GetScreenlockStateHandler())
439 return;
441 EasyUnlockScreenlockStateHandler::HardlockState state;
442 bool has_persisted_state = GetPersistedHardlockState(&state);
443 if (!has_persisted_state)
444 return;
446 if (state == EasyUnlockScreenlockStateHandler::NO_HARDLOCK) {
447 // Show connecting icon early when there is a persisted non hardlock state.
448 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING);
449 } else {
450 screenlock_state_handler_->MaybeShowHardlockUI();
454 EasyUnlockScreenlockStateHandler*
455 EasyUnlockService::GetScreenlockStateHandler() {
456 if (!IsAllowed())
457 return NULL;
458 if (!screenlock_state_handler_) {
459 screenlock_state_handler_.reset(new EasyUnlockScreenlockStateHandler(
460 GetUserEmail(), GetHardlockState(),
461 proximity_auth::ScreenlockBridge::Get()));
463 return screenlock_state_handler_.get();
466 bool EasyUnlockService::UpdateScreenlockState(ScreenlockState state) {
467 EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
468 if (!handler)
469 return false;
471 handler->ChangeState(state);
473 if (state == ScreenlockState::AUTHENTICATED) {
474 #if defined(OS_CHROMEOS)
475 if (power_monitor_)
476 power_monitor_->RecordStartUpTime();
477 #endif
478 } else if (auth_attempt_.get()) {
479 // Clean up existing auth attempt if we can no longer authenticate the
480 // remote device.
481 auth_attempt_.reset();
483 if (!handler->InStateValidOnRemoteAuthFailure())
484 HandleAuthFailure(GetUserEmail());
487 FOR_EACH_OBSERVER(
488 EasyUnlockServiceObserver, observers_, OnScreenlockStateChanged(state));
489 return true;
492 ScreenlockState EasyUnlockService::GetScreenlockState() {
493 EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
494 if (!handler)
495 return ScreenlockState::INACTIVE;
497 return handler->state();
500 void EasyUnlockService::AttemptAuth(const std::string& user_id) {
501 AttemptAuth(user_id, AttemptAuthCallback());
504 void EasyUnlockService::AttemptAuth(const std::string& user_id,
505 const AttemptAuthCallback& callback) {
506 const EasyUnlockAuthAttempt::Type auth_attempt_type =
507 GetType() == TYPE_REGULAR ? EasyUnlockAuthAttempt::TYPE_UNLOCK
508 : EasyUnlockAuthAttempt::TYPE_SIGNIN;
509 const std::string user_email = GetUserEmail();
510 if (user_email.empty()) {
511 LOG(ERROR) << "Empty user email. Refresh token might go bad.";
512 if (!callback.is_null()) {
513 const bool kFailure = false;
514 callback.Run(auth_attempt_type, kFailure, user_id, std::string(),
515 std::string());
517 return;
520 CHECK_EQ(GetUserEmail(), user_id);
522 auth_attempt_.reset(new EasyUnlockAuthAttempt(app_manager_.get(), user_id,
523 auth_attempt_type, callback));
524 if (!auth_attempt_->Start())
525 auth_attempt_.reset();
528 void EasyUnlockService::FinalizeUnlock(bool success) {
529 if (!auth_attempt_.get())
530 return;
532 this->OnWillFinalizeUnlock(success);
533 auth_attempt_->FinalizeUnlock(GetUserEmail(), success);
534 auth_attempt_.reset();
535 // TODO(isherman): If observing screen unlock events, is there a race
536 // condition in terms of reading the service's state vs. the app setting the
537 // state?
539 // Make sure that the lock screen is updated on failure.
540 if (!success) {
541 RecordEasyUnlockScreenUnlockEvent(EASY_UNLOCK_FAILURE);
542 HandleAuthFailure(GetUserEmail());
546 void EasyUnlockService::FinalizeSignin(const std::string& key) {
547 if (!auth_attempt_.get())
548 return;
549 std::string wrapped_secret = GetWrappedSecret();
550 if (!wrapped_secret.empty())
551 auth_attempt_->FinalizeSignin(GetUserEmail(), wrapped_secret, key);
552 auth_attempt_.reset();
554 // Processing empty key is equivalent to auth cancellation. In this case the
555 // signin request will not actually be processed by login stack, so the lock
556 // screen state should be set from here.
557 if (key.empty())
558 HandleAuthFailure(GetUserEmail());
561 void EasyUnlockService::HandleAuthFailure(const std::string& user_id) {
562 if (user_id != GetUserEmail())
563 return;
565 if (!screenlock_state_handler_.get())
566 return;
568 screenlock_state_handler_->SetHardlockState(
569 EasyUnlockScreenlockStateHandler::LOGIN_FAILED);
572 void EasyUnlockService::CheckCryptohomeKeysAndMaybeHardlock() {
573 #if defined(OS_CHROMEOS)
574 std::string user_id = GetUserEmail();
575 if (user_id.empty())
576 return;
578 const base::ListValue* device_list = GetRemoteDevices();
579 std::set<std::string> paired_devices;
580 if (device_list) {
581 chromeos::EasyUnlockDeviceKeyDataList parsed_paired;
582 chromeos::EasyUnlockKeyManager::RemoteDeviceListToDeviceDataList(
583 *device_list, &parsed_paired);
584 for (const auto& device_key_data : parsed_paired)
585 paired_devices.insert(device_key_data.psk);
587 if (paired_devices.empty()) {
588 SetHardlockState(EasyUnlockScreenlockStateHandler::NO_PAIRING);
589 return;
592 // No need to compare if a change is already recorded.
593 if (GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_CHANGED ||
594 GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_ADDED) {
595 return;
598 chromeos::EasyUnlockKeyManager* key_manager =
599 chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager();
600 DCHECK(key_manager);
602 key_manager->GetDeviceDataList(
603 chromeos::UserContext(user_id),
604 base::Bind(&EasyUnlockService::OnCryptohomeKeysFetchedForChecking,
605 weak_ptr_factory_.GetWeakPtr(),
606 user_id,
607 paired_devices));
608 #endif
611 void EasyUnlockService::SetTrialRun() {
612 DCHECK_EQ(GetType(), TYPE_REGULAR);
614 EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
615 if (handler)
616 handler->SetTrialRun();
619 void EasyUnlockService::RecordClickOnLockIcon() {
620 if (screenlock_state_handler_)
621 screenlock_state_handler_->RecordClickOnLockIcon();
624 void EasyUnlockService::AddObserver(EasyUnlockServiceObserver* observer) {
625 observers_.AddObserver(observer);
628 void EasyUnlockService::RemoveObserver(EasyUnlockServiceObserver* observer) {
629 observers_.RemoveObserver(observer);
632 scoped_ptr<proximity_auth::CryptAuthClientFactory>
633 EasyUnlockService::CreateCryptAuthClientFactory() {
634 return make_scoped_ptr(new proximity_auth::CryptAuthClientFactoryImpl(
635 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()),
636 SigninManagerFactory::GetForProfile(profile())
637 ->GetAuthenticatedAccountId(),
638 profile()->GetRequestContext(), GetDeviceClassifier()));
641 cryptauth::DeviceClassifier EasyUnlockService::GetDeviceClassifier() {
642 cryptauth::DeviceClassifier device_classifier;
644 #if defined(OS_CHROMEOS)
645 int32 major_version, minor_version, bugfix_version;
646 // TODO(tengs): base::OperatingSystemVersionNumbers only works for ChromeOS.
647 // We need to get different numbers for other platforms.
648 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
649 &bugfix_version);
650 device_classifier.set_device_os_version_code(major_version);
651 device_classifier.set_device_type(cryptauth::CHROME);
652 #endif
654 chrome::VersionInfo version_info;
655 const std::vector<uint32_t>& version_components =
656 base::Version(version_info.Version()).components();
657 if (version_components.size() > 0)
658 device_classifier.set_device_software_version_code(version_components[0]);
660 device_classifier.set_device_software_package(version_info.Name());
661 return device_classifier;
664 void EasyUnlockService::Shutdown() {
665 if (shut_down_)
666 return;
667 shut_down_ = true;
669 ShutdownInternal();
671 ResetScreenlockState();
672 bluetooth_detector_.reset();
673 #if defined(OS_CHROMEOS)
674 power_monitor_.reset();
675 #endif
677 weak_ptr_factory_.InvalidateWeakPtrs();
680 void EasyUnlockService::ReloadAppAndLockScreen() {
681 // Make sure lock screen state set by the extension gets reset.
682 ResetScreenlockState();
683 app_manager_->ReloadApp();
684 NotifyUserUpdated();
687 void EasyUnlockService::UpdateAppState() {
688 if (IsAllowed()) {
689 EnsureTpmKeyPresentIfNeeded();
690 app_manager_->LoadApp();
691 NotifyUserUpdated();
693 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
694 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery) &&
695 GetType() == EasyUnlockService::TYPE_REGULAR &&
696 !proximity_auth_ble_system_) {
697 proximity_auth_ble_system_.reset(
698 new proximity_auth::ProximityAuthBleSystem(
699 proximity_auth::ScreenlockBridge::Get(), &proximity_auth_client_,
700 CreateCryptAuthClientFactory()));
703 #if defined(OS_CHROMEOS)
704 if (!power_monitor_)
705 power_monitor_.reset(new PowerMonitor(this));
706 #endif
707 } else {
708 bool bluetooth_waking_up = false;
709 #if defined(OS_CHROMEOS)
710 // If the service is not allowed due to bluetooth not being detected just
711 // after system suspend is done, give bluetooth more time to be detected
712 // before disabling the app (and resetting screenlock state).
713 bluetooth_waking_up =
714 power_monitor_.get() && power_monitor_->waking_up() &&
715 !bluetooth_detector_->IsPresent();
716 #endif
718 if (!bluetooth_waking_up) {
719 app_manager_->DisableAppIfLoaded();
720 ResetScreenlockState();
721 proximity_auth_ble_system_.reset();
722 #if defined(OS_CHROMEOS)
723 power_monitor_.reset();
724 #endif
729 void EasyUnlockService::DisableAppWithoutResettingScreenlockState() {
730 app_manager_->DisableAppIfLoaded();
733 void EasyUnlockService::NotifyUserUpdated() {
734 std::string user_id = GetUserEmail();
735 if (user_id.empty())
736 return;
738 // Notify the easy unlock app that the user info changed.
739 bool logged_in = GetType() == TYPE_REGULAR;
740 bool data_ready = logged_in || GetRemoteDevices() != NULL;
741 app_manager_->SendUserUpdatedEvent(user_id, logged_in, data_ready);
744 void EasyUnlockService::NotifyTurnOffOperationStatusChanged() {
745 FOR_EACH_OBSERVER(
746 EasyUnlockServiceObserver, observers_, OnTurnOffOperationStatusChanged());
749 void EasyUnlockService::ResetScreenlockState() {
750 screenlock_state_handler_.reset();
751 auth_attempt_.reset();
754 void EasyUnlockService::SetScreenlockHardlockedState(
755 EasyUnlockScreenlockStateHandler::HardlockState state) {
756 if (screenlock_state_handler_)
757 screenlock_state_handler_->SetHardlockState(state);
758 if (state != EasyUnlockScreenlockStateHandler::NO_HARDLOCK)
759 auth_attempt_.reset();
762 void EasyUnlockService::InitializeOnAppManagerReady() {
763 CHECK(app_manager_.get());
765 InitializeInternal();
766 bluetooth_detector_->Initialize();
769 void EasyUnlockService::OnBluetoothAdapterPresentChanged() {
770 UpdateAppState();
772 // Whether we've already passed Bluetooth availability information to UMA.
773 // This is static because there may be multiple instances and we want to
774 // report this system-level stat only once per run of Chrome.
775 static bool bluetooth_adapter_has_been_reported = false;
777 if (!bluetooth_adapter_has_been_reported) {
778 bluetooth_adapter_has_been_reported = true;
779 int bttype = BT_NO_ADAPTER;
780 if (bluetooth_detector_->IsPresent()) {
781 bttype = BT_LOW_ENERGY_CAPABLE;
782 #if defined(OS_WIN)
783 if (base::win::GetVersion() < base::win::VERSION_WIN8) {
784 bttype = BT_NORMAL;
786 #endif
788 UMA_HISTOGRAM_ENUMERATION(
789 "EasyUnlock.BluetoothAvailability", bttype, BT_MAX_TYPE);
793 void EasyUnlockService::SetHardlockStateForUser(
794 const std::string& user_id,
795 EasyUnlockScreenlockStateHandler::HardlockState state) {
796 DCHECK(!user_id.empty());
798 PrefService* local_state = GetLocalState();
799 if (!local_state)
800 return;
802 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
803 update->SetIntegerWithoutPathExpansion(user_id, static_cast<int>(state));
805 if (GetUserEmail() == user_id)
806 SetScreenlockHardlockedState(state);
809 EasyUnlockAuthEvent EasyUnlockService::GetPasswordAuthEvent() const {
810 DCHECK(IsEnabled());
812 if (GetHardlockState() != EasyUnlockScreenlockStateHandler::NO_HARDLOCK) {
813 switch (GetHardlockState()) {
814 case EasyUnlockScreenlockStateHandler::NO_HARDLOCK:
815 NOTREACHED();
816 return EASY_UNLOCK_AUTH_EVENT_COUNT;
817 case EasyUnlockScreenlockStateHandler::NO_PAIRING:
818 return PASSWORD_ENTRY_NO_PAIRING;
819 case EasyUnlockScreenlockStateHandler::USER_HARDLOCK:
820 return PASSWORD_ENTRY_USER_HARDLOCK;
821 case EasyUnlockScreenlockStateHandler::PAIRING_CHANGED:
822 return PASSWORD_ENTRY_PAIRING_CHANGED;
823 case EasyUnlockScreenlockStateHandler::LOGIN_FAILED:
824 return PASSWORD_ENTRY_LOGIN_FAILED;
825 case EasyUnlockScreenlockStateHandler::PAIRING_ADDED:
826 return PASSWORD_ENTRY_PAIRING_ADDED;
828 } else if (!screenlock_state_handler()) {
829 return PASSWORD_ENTRY_NO_SCREENLOCK_STATE_HANDLER;
830 } else {
831 switch (screenlock_state_handler()->state()) {
832 case ScreenlockState::INACTIVE:
833 return PASSWORD_ENTRY_SERVICE_NOT_ACTIVE;
834 case ScreenlockState::NO_BLUETOOTH:
835 return PASSWORD_ENTRY_NO_BLUETOOTH;
836 case ScreenlockState::BLUETOOTH_CONNECTING:
837 return PASSWORD_ENTRY_BLUETOOTH_CONNECTING;
838 case ScreenlockState::NO_PHONE:
839 return PASSWORD_ENTRY_NO_PHONE;
840 case ScreenlockState::PHONE_NOT_AUTHENTICATED:
841 return PASSWORD_ENTRY_PHONE_NOT_AUTHENTICATED;
842 case ScreenlockState::PHONE_LOCKED:
843 return PASSWORD_ENTRY_PHONE_LOCKED;
844 case ScreenlockState::PHONE_NOT_LOCKABLE:
845 return PASSWORD_ENTRY_PHONE_NOT_LOCKABLE;
846 case ScreenlockState::PHONE_UNSUPPORTED:
847 return PASSWORD_ENTRY_PHONE_UNSUPPORTED;
848 case ScreenlockState::RSSI_TOO_LOW:
849 return PASSWORD_ENTRY_RSSI_TOO_LOW;
850 case ScreenlockState::TX_POWER_TOO_HIGH:
851 return PASSWORD_ENTRY_TX_POWER_TOO_HIGH;
852 case ScreenlockState::PHONE_LOCKED_AND_TX_POWER_TOO_HIGH:
853 return PASSWORD_ENTRY_PHONE_LOCKED_AND_TX_POWER_TOO_HIGH;
854 case ScreenlockState::AUTHENTICATED:
855 return PASSWORD_ENTRY_WITH_AUTHENTICATED_PHONE;
859 NOTREACHED();
860 return EASY_UNLOCK_AUTH_EVENT_COUNT;
863 #if defined(OS_CHROMEOS)
864 void EasyUnlockService::OnCryptohomeKeysFetchedForChecking(
865 const std::string& user_id,
866 const std::set<std::string> paired_devices,
867 bool success,
868 const chromeos::EasyUnlockDeviceKeyDataList& key_data_list) {
869 DCHECK(!user_id.empty() && !paired_devices.empty());
871 if (!success) {
872 SetHardlockStateForUser(user_id,
873 EasyUnlockScreenlockStateHandler::NO_PAIRING);
874 return;
877 std::set<std::string> devices_in_cryptohome;
878 for (const auto& device_key_data : key_data_list)
879 devices_in_cryptohome.insert(device_key_data.psk);
881 if (paired_devices != devices_in_cryptohome ||
882 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING) {
883 SetHardlockStateForUser(
884 user_id,
885 devices_in_cryptohome.empty()
886 ? EasyUnlockScreenlockStateHandler::PAIRING_ADDED
887 : EasyUnlockScreenlockStateHandler::PAIRING_CHANGED);
890 #endif
892 void EasyUnlockService::PrepareForSuspend() {
893 app_manager_->DisableAppIfLoaded();
894 if (screenlock_state_handler_ && screenlock_state_handler_->IsActive())
895 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING);
898 void EasyUnlockService::EnsureTpmKeyPresentIfNeeded() {
899 if (tpm_key_checked_ || GetType() != TYPE_REGULAR || GetUserEmail().empty() ||
900 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING) {
901 return;
904 #if defined(OS_CHROMEOS)
905 // If this is called before the session is started, the chances are Chrome
906 // is restarting in order to apply user flags. Don't check TPM keys in this
907 // case.
908 if (!user_manager::UserManager::Get() ||
909 !user_manager::UserManager::Get()->IsSessionStarted())
910 return;
912 // TODO(tbarzic): Set check_private_key only if previous sign-in attempt
913 // failed.
914 EasyUnlockTpmKeyManagerFactory::GetInstance()->Get(profile_)
915 ->PrepareTpmKey(true /* check_private_key */,
916 base::Closure());
917 #endif // defined(OS_CHROMEOS)
919 tpm_key_checked_ = true;