Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / signin / easy_unlock_service.cc
blobf261a3581727b6adbf36062c9f45f6747caa33bf
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/thread_task_runner_handle.h"
18 #include "base/time/time.h"
19 #include "base/values.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/signin/easy_unlock_app_manager.h"
23 #include "chrome/browser/signin/easy_unlock_service_factory.h"
24 #include "chrome/browser/signin/easy_unlock_service_observer.h"
25 #include "chrome/browser/signin/screenlock_bridge.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/extensions/extension_constants.h"
28 #include "chrome/common/pref_names.h"
29 #include "components/pref_registry/pref_registry_syncable.h"
30 #include "components/proximity_auth/switches.h"
31 #include "components/user_manager/user.h"
32 #include "device/bluetooth/bluetooth_adapter.h"
33 #include "device/bluetooth/bluetooth_adapter_factory.h"
35 #if defined(OS_CHROMEOS)
36 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
37 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
38 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
39 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
40 #include "chrome/browser/chromeos/profiles/profile_helper.h"
41 #include "chromeos/dbus/dbus_thread_manager.h"
42 #include "chromeos/dbus/power_manager_client.h"
43 #include "components/user_manager/user_manager.h"
44 #endif
46 #if defined(OS_WIN)
47 #include "base/win/windows_version.h"
48 #endif
50 namespace {
52 enum BluetoothType {
53 BT_NO_ADAPTER,
54 BT_NORMAL,
55 BT_LOW_ENERGY_CAPABLE,
56 BT_MAX_TYPE
59 PrefService* GetLocalState() {
60 return g_browser_process ? g_browser_process->local_state() : NULL;
63 } // namespace
65 EasyUnlockService::UserSettings::UserSettings()
66 : require_close_proximity(false) {
69 EasyUnlockService::UserSettings::~UserSettings() {
72 // static
73 EasyUnlockService* EasyUnlockService::Get(Profile* profile) {
74 return EasyUnlockServiceFactory::GetForProfile(profile);
77 // static
78 EasyUnlockService* EasyUnlockService::GetForUser(
79 const user_manager::User& user) {
80 #if defined(OS_CHROMEOS)
81 Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(&user);
82 if (!profile)
83 return NULL;
84 return EasyUnlockService::Get(profile);
85 #else
86 return NULL;
87 #endif
90 // static
91 bool EasyUnlockService::IsSignInEnabled() {
92 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
93 proximity_auth::switches::kDisableEasyUnlock);
96 class EasyUnlockService::BluetoothDetector
97 : public device::BluetoothAdapter::Observer,
98 public apps::AppLifetimeMonitor::Observer {
99 public:
100 explicit BluetoothDetector(EasyUnlockService* service)
101 : service_(service),
102 weak_ptr_factory_(this) {
103 apps::AppLifetimeMonitorFactory::GetForProfile(service_->profile())
104 ->AddObserver(this);
107 ~BluetoothDetector() override {
108 if (adapter_.get())
109 adapter_->RemoveObserver(this);
110 apps::AppLifetimeMonitorFactory::GetForProfile(service_->profile())
111 ->RemoveObserver(this);
114 void Initialize() {
115 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
116 return;
118 device::BluetoothAdapterFactory::GetAdapter(
119 base::Bind(&BluetoothDetector::OnAdapterInitialized,
120 weak_ptr_factory_.GetWeakPtr()));
123 bool IsPresent() const { return adapter_.get() && adapter_->IsPresent(); }
125 // device::BluetoothAdapter::Observer:
126 void AdapterPresentChanged(device::BluetoothAdapter* adapter,
127 bool present) override {
128 service_->OnBluetoothAdapterPresentChanged();
131 device::BluetoothAdapter* getAdapter() {
132 return adapter_.get();
135 private:
136 void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter) {
137 adapter_ = adapter;
138 adapter_->AddObserver(this);
139 service_->OnBluetoothAdapterPresentChanged();
141 // TODO(tengs): At the moment, there is no way for Bluetooth discoverability
142 // to be turned on except through the Easy Unlock setup. If we step on any
143 // toes in the future then we need to revisit this guard.
144 if (adapter_->IsDiscoverable())
145 TurnOffBluetoothDiscoverability();
147 #if !defined(OS_CHROMEOS)
148 // Bluetooth detection causes serious performance degradations on Mac
149 // and possibly other platforms as well: http://crbug.com/467316
150 // Since this feature is currently only offered for ChromeOS we just
151 // turn it off on other platforms once the inforamtion about the
152 // adapter has been gathered and reported.
153 // TODO(bcwhite,xiyuan): Revisit when non-chromeos platforms are supported.
154 adapter_->RemoveObserver(this);
155 adapter_ = NULL;
156 #endif // !defined(OS_CHROMEOS)
159 // apps::AppLifetimeMonitor::Observer:
160 void OnAppDeactivated(Profile* profile, const std::string& app_id) override {
161 // TODO(tengs): Refactor the lifetime management to EasyUnlockAppManager.
162 if (app_id == extension_misc::kEasyUnlockAppId)
163 TurnOffBluetoothDiscoverability();
166 void OnAppStop(Profile* profile, const std::string& app_id) override {
167 // TODO(tengs): Refactor the lifetime management to EasyUnlockAppManager.
168 if (app_id == extension_misc::kEasyUnlockAppId)
169 TurnOffBluetoothDiscoverability();
172 void TurnOffBluetoothDiscoverability() {
173 if (adapter_) {
174 adapter_->SetDiscoverable(
175 false, base::Bind(&base::DoNothing), base::Bind(&base::DoNothing));
179 // Owner of this class and should out-live this class.
180 EasyUnlockService* service_;
181 scoped_refptr<device::BluetoothAdapter> adapter_;
182 base::WeakPtrFactory<BluetoothDetector> weak_ptr_factory_;
184 DISALLOW_COPY_AND_ASSIGN(BluetoothDetector);
187 #if defined(OS_CHROMEOS)
188 class EasyUnlockService::PowerMonitor
189 : public chromeos::PowerManagerClient::Observer {
190 public:
191 explicit PowerMonitor(EasyUnlockService* service)
192 : service_(service),
193 waking_up_(false),
194 weak_ptr_factory_(this) {
195 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
196 AddObserver(this);
199 ~PowerMonitor() override {
200 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
201 RemoveObserver(this);
204 // Called when the remote device has been authenticated to record the time
205 // delta from waking up. No time will be recorded if the start-up time has
206 // already been recorded or if the system never went to sleep previously.
207 void RecordStartUpTime() {
208 if (wake_up_time_.is_null())
209 return;
210 UMA_HISTOGRAM_MEDIUM_TIMES(
211 "EasyUnlock.StartupTimeFromSuspend",
212 base::Time::Now() - wake_up_time_);
213 wake_up_time_ = base::Time();
216 bool waking_up() const { return waking_up_; }
218 private:
219 // chromeos::PowerManagerClient::Observer:
220 void SuspendImminent() override { service_->PrepareForSuspend(); }
222 void SuspendDone(const base::TimeDelta& sleep_duration) override {
223 waking_up_ = true;
224 wake_up_time_ = base::Time::Now();
225 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
226 FROM_HERE,
227 base::Bind(&PowerMonitor::ResetWakingUp,
228 weak_ptr_factory_.GetWeakPtr()),
229 base::TimeDelta::FromSeconds(5));
230 service_->OnSuspendDone();
231 service_->UpdateAppState();
232 // Note that |this| may get deleted after |UpdateAppState| is called.
235 void ResetWakingUp() {
236 waking_up_ = false;
237 service_->UpdateAppState();
240 EasyUnlockService* service_;
241 bool waking_up_;
242 base::Time wake_up_time_;
243 base::WeakPtrFactory<PowerMonitor> weak_ptr_factory_;
245 DISALLOW_COPY_AND_ASSIGN(PowerMonitor);
247 #endif
249 EasyUnlockService::EasyUnlockService(Profile* profile)
250 : profile_(profile),
251 bluetooth_detector_(new BluetoothDetector(this)),
252 shut_down_(false),
253 tpm_key_checked_(false),
254 weak_ptr_factory_(this) {
257 EasyUnlockService::~EasyUnlockService() {
260 // static
261 void EasyUnlockService::RegisterProfilePrefs(
262 user_prefs::PrefRegistrySyncable* registry) {
263 registry->RegisterBooleanPref(
264 prefs::kEasyUnlockAllowed,
265 true,
266 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
267 registry->RegisterBooleanPref(
268 prefs::kEasyUnlockEnabled,
269 false,
270 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
271 registry->RegisterDictionaryPref(
272 prefs::kEasyUnlockPairing,
273 new base::DictionaryValue(),
274 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
275 registry->RegisterBooleanPref(
276 prefs::kEasyUnlockProximityRequired,
277 false,
278 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
281 // static
282 void EasyUnlockService::RegisterPrefs(PrefRegistrySimple* registry) {
283 registry->RegisterStringPref(prefs::kEasyUnlockDeviceId, std::string());
284 registry->RegisterDictionaryPref(prefs::kEasyUnlockHardlockState);
285 registry->RegisterDictionaryPref(prefs::kEasyUnlockLocalStateUserPrefs);
286 #if defined(OS_CHROMEOS)
287 EasyUnlockTpmKeyManager::RegisterLocalStatePrefs(registry);
288 #endif
291 // static
292 void EasyUnlockService::ResetLocalStateForUser(const std::string& user_id) {
293 DCHECK(!user_id.empty());
295 PrefService* local_state = GetLocalState();
296 if (!local_state)
297 return;
299 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
300 update->RemoveWithoutPathExpansion(user_id, NULL);
302 #if defined(OS_CHROMEOS)
303 EasyUnlockTpmKeyManager::ResetLocalStateForUser(user_id);
304 #endif
307 // static
308 EasyUnlockService::UserSettings EasyUnlockService::GetUserSettings(
309 const std::string& user_id) {
310 DCHECK(!user_id.empty());
311 UserSettings user_settings;
313 PrefService* local_state = GetLocalState();
314 if (!local_state)
315 return user_settings;
317 const base::DictionaryValue* all_user_prefs_dict =
318 local_state->GetDictionary(prefs::kEasyUnlockLocalStateUserPrefs);
319 if (!all_user_prefs_dict)
320 return user_settings;
322 const base::DictionaryValue* user_prefs_dict;
323 if (!all_user_prefs_dict->GetDictionaryWithoutPathExpansion(user_id,
324 &user_prefs_dict))
325 return user_settings;
327 user_prefs_dict->GetBooleanWithoutPathExpansion(
328 prefs::kEasyUnlockProximityRequired,
329 &user_settings.require_close_proximity);
331 return user_settings;
334 // static
335 std::string EasyUnlockService::GetDeviceId() {
336 PrefService* local_state = GetLocalState();
337 if (!local_state)
338 return std::string();
340 std::string device_id = local_state->GetString(prefs::kEasyUnlockDeviceId);
341 if (device_id.empty()) {
342 device_id = base::GenerateGUID();
343 local_state->SetString(prefs::kEasyUnlockDeviceId, device_id);
345 return device_id;
348 void EasyUnlockService::Initialize(
349 scoped_ptr<EasyUnlockAppManager> app_manager) {
350 app_manager_ = app_manager.Pass();
351 app_manager_->EnsureReady(
352 base::Bind(&EasyUnlockService::InitializeOnAppManagerReady,
353 weak_ptr_factory_.GetWeakPtr()));
356 bool EasyUnlockService::IsAllowed() const {
357 if (shut_down_)
358 return false;
360 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
361 proximity_auth::switches::kDisableEasyUnlock)) {
362 return false;
365 if (!IsAllowedInternal())
366 return false;
368 #if defined(OS_CHROMEOS)
369 if (!bluetooth_detector_->IsPresent())
370 return false;
372 return true;
373 #else
374 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
375 return false;
376 #endif
379 bool EasyUnlockService::IsEnabled() const {
380 // The feature is enabled iff there are any paired devices.
381 const base::ListValue* devices = GetRemoteDevices();
382 return devices && !devices->empty();
385 void EasyUnlockService::OpenSetupApp() {
386 app_manager_->LaunchSetup();
389 void EasyUnlockService::SetHardlockState(
390 EasyUnlockScreenlockStateHandler::HardlockState state) {
391 const std::string user_id = GetUserEmail();
392 if (user_id.empty())
393 return;
395 if (state == GetHardlockState())
396 return;
398 SetHardlockStateForUser(user_id, state);
401 EasyUnlockScreenlockStateHandler::HardlockState
402 EasyUnlockService::GetHardlockState() const {
403 EasyUnlockScreenlockStateHandler::HardlockState state;
404 if (GetPersistedHardlockState(&state))
405 return state;
407 return EasyUnlockScreenlockStateHandler::NO_HARDLOCK;
410 bool EasyUnlockService::GetPersistedHardlockState(
411 EasyUnlockScreenlockStateHandler::HardlockState* state) const {
412 std::string user_id = GetUserEmail();
413 if (user_id.empty())
414 return false;
416 PrefService* local_state = GetLocalState();
417 if (!local_state)
418 return false;
420 const base::DictionaryValue* dict =
421 local_state->GetDictionary(prefs::kEasyUnlockHardlockState);
422 int state_int;
423 if (dict && dict->GetIntegerWithoutPathExpansion(user_id, &state_int)) {
424 *state =
425 static_cast<EasyUnlockScreenlockStateHandler::HardlockState>(state_int);
426 return true;
429 return false;
432 void EasyUnlockService::ShowInitialUserState() {
433 if (!GetScreenlockStateHandler())
434 return;
436 EasyUnlockScreenlockStateHandler::HardlockState state;
437 bool has_persisted_state = GetPersistedHardlockState(&state);
438 if (!has_persisted_state)
439 return;
441 if (state == EasyUnlockScreenlockStateHandler::NO_HARDLOCK) {
442 // Show connecting icon early when there is a persisted non hardlock state.
443 UpdateScreenlockState(
444 EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING);
445 } else {
446 screenlock_state_handler_->MaybeShowHardlockUI();
450 EasyUnlockScreenlockStateHandler*
451 EasyUnlockService::GetScreenlockStateHandler() {
452 if (!IsAllowed())
453 return NULL;
454 if (!screenlock_state_handler_) {
455 screenlock_state_handler_.reset(new EasyUnlockScreenlockStateHandler(
456 GetUserEmail(),
457 GetHardlockState(),
458 ScreenlockBridge::Get()));
460 return screenlock_state_handler_.get();
463 bool EasyUnlockService::UpdateScreenlockState(
464 EasyUnlockScreenlockStateHandler::State state) {
465 EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
466 if (!handler)
467 return false;
469 handler->ChangeState(state);
471 if (state == EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED) {
472 #if defined(OS_CHROMEOS)
473 if (power_monitor_)
474 power_monitor_->RecordStartUpTime();
475 #endif
476 } else if (auth_attempt_.get()) {
477 // Clean up existing auth attempt if we can no longer authenticate the
478 // remote device.
479 auth_attempt_.reset();
481 if (!handler->InStateValidOnRemoteAuthFailure())
482 HandleAuthFailure(GetUserEmail());
485 FOR_EACH_OBSERVER(
486 EasyUnlockServiceObserver, observers_, OnScreenlockStateChanged(state));
487 return true;
490 EasyUnlockScreenlockStateHandler::State
491 EasyUnlockService::GetScreenlockState() {
492 EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
493 if (!handler)
494 return EasyUnlockScreenlockStateHandler::STATE_INACTIVE;
496 return handler->state();
499 void EasyUnlockService::AttemptAuth(const std::string& user_id) {
500 AttemptAuth(user_id, AttemptAuthCallback());
503 void EasyUnlockService::AttemptAuth(const std::string& user_id,
504 const AttemptAuthCallback& callback) {
505 CHECK_EQ(GetUserEmail(), user_id);
507 auth_attempt_.reset(new EasyUnlockAuthAttempt(
508 app_manager_.get(), user_id,
509 GetType() == TYPE_REGULAR ? EasyUnlockAuthAttempt::TYPE_UNLOCK
510 : EasyUnlockAuthAttempt::TYPE_SIGNIN,
511 callback));
512 if (!auth_attempt_->Start())
513 auth_attempt_.reset();
516 void EasyUnlockService::FinalizeUnlock(bool success) {
517 if (!auth_attempt_.get())
518 return;
520 this->OnWillFinalizeUnlock(success);
521 auth_attempt_->FinalizeUnlock(GetUserEmail(), success);
522 auth_attempt_.reset();
523 // TODO(isherman): If observing screen unlock events, is there a race
524 // condition in terms of reading the service's state vs. the app setting the
525 // state?
527 // Make sure that the lock screen is updated on failure.
528 if (!success) {
529 RecordEasyUnlockScreenUnlockEvent(EASY_UNLOCK_FAILURE);
530 HandleAuthFailure(GetUserEmail());
534 void EasyUnlockService::FinalizeSignin(const std::string& key) {
535 if (!auth_attempt_.get())
536 return;
537 std::string wrapped_secret = GetWrappedSecret();
538 if (!wrapped_secret.empty())
539 auth_attempt_->FinalizeSignin(GetUserEmail(), wrapped_secret, key);
540 auth_attempt_.reset();
542 // Processing empty key is equivalent to auth cancellation. In this case the
543 // signin request will not actually be processed by login stack, so the lock
544 // screen state should be set from here.
545 if (key.empty())
546 HandleAuthFailure(GetUserEmail());
549 void EasyUnlockService::HandleAuthFailure(const std::string& user_id) {
550 if (user_id != GetUserEmail())
551 return;
553 if (!screenlock_state_handler_.get())
554 return;
556 screenlock_state_handler_->SetHardlockState(
557 EasyUnlockScreenlockStateHandler::LOGIN_FAILED);
560 void EasyUnlockService::CheckCryptohomeKeysAndMaybeHardlock() {
561 #if defined(OS_CHROMEOS)
562 std::string user_id = GetUserEmail();
563 if (user_id.empty())
564 return;
566 const base::ListValue* device_list = GetRemoteDevices();
567 std::set<std::string> paired_devices;
568 if (device_list) {
569 chromeos::EasyUnlockDeviceKeyDataList parsed_paired;
570 chromeos::EasyUnlockKeyManager::RemoteDeviceListToDeviceDataList(
571 *device_list, &parsed_paired);
572 for (const auto& device_key_data : parsed_paired)
573 paired_devices.insert(device_key_data.psk);
575 if (paired_devices.empty()) {
576 SetHardlockState(EasyUnlockScreenlockStateHandler::NO_PAIRING);
577 return;
580 // No need to compare if a change is already recorded.
581 if (GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_CHANGED ||
582 GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_ADDED) {
583 return;
586 chromeos::EasyUnlockKeyManager* key_manager =
587 chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager();
588 DCHECK(key_manager);
590 key_manager->GetDeviceDataList(
591 chromeos::UserContext(user_id),
592 base::Bind(&EasyUnlockService::OnCryptohomeKeysFetchedForChecking,
593 weak_ptr_factory_.GetWeakPtr(),
594 user_id,
595 paired_devices));
596 #endif
599 void EasyUnlockService::SetTrialRun() {
600 DCHECK_EQ(GetType(), TYPE_REGULAR);
602 EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
603 if (handler)
604 handler->SetTrialRun();
607 void EasyUnlockService::RecordClickOnLockIcon() {
608 if (screenlock_state_handler_)
609 screenlock_state_handler_->RecordClickOnLockIcon();
612 void EasyUnlockService::AddObserver(EasyUnlockServiceObserver* observer) {
613 observers_.AddObserver(observer);
616 void EasyUnlockService::RemoveObserver(EasyUnlockServiceObserver* observer) {
617 observers_.RemoveObserver(observer);
620 void EasyUnlockService::Shutdown() {
621 if (shut_down_)
622 return;
623 shut_down_ = true;
625 ShutdownInternal();
627 ResetScreenlockState();
628 bluetooth_detector_.reset();
629 #if defined(OS_CHROMEOS)
630 power_monitor_.reset();
631 #endif
633 weak_ptr_factory_.InvalidateWeakPtrs();
636 void EasyUnlockService::ReloadAppAndLockScreen() {
637 // Make sure lock screen state set by the extension gets reset.
638 ResetScreenlockState();
639 app_manager_->ReloadApp();
640 NotifyUserUpdated();
643 void EasyUnlockService::UpdateAppState() {
644 if (IsAllowed()) {
645 EnsureTpmKeyPresentIfNeeded();
646 app_manager_->LoadApp();
647 NotifyUserUpdated();
649 #if defined(OS_CHROMEOS)
650 if (!power_monitor_)
651 power_monitor_.reset(new PowerMonitor(this));
652 #endif
653 } else {
654 bool bluetooth_waking_up = false;
655 #if defined(OS_CHROMEOS)
656 // If the service is not allowed due to bluetooth not being detected just
657 // after system suspend is done, give bluetooth more time to be detected
658 // before disabling the app (and resetting screenlock state).
659 bluetooth_waking_up =
660 power_monitor_.get() && power_monitor_->waking_up() &&
661 !bluetooth_detector_->IsPresent();
662 #endif
664 if (!bluetooth_waking_up) {
665 app_manager_->DisableAppIfLoaded();
666 ResetScreenlockState();
667 #if defined(OS_CHROMEOS)
668 power_monitor_.reset();
669 #endif
674 void EasyUnlockService::DisableAppWithoutResettingScreenlockState() {
675 app_manager_->DisableAppIfLoaded();
678 void EasyUnlockService::NotifyUserUpdated() {
679 std::string user_id = GetUserEmail();
680 if (user_id.empty())
681 return;
683 // Notify the easy unlock app that the user info changed.
684 bool logged_in = GetType() == TYPE_REGULAR;
685 bool data_ready = logged_in || GetRemoteDevices() != NULL;
686 app_manager_->SendUserUpdatedEvent(user_id, logged_in, data_ready);
689 void EasyUnlockService::NotifyTurnOffOperationStatusChanged() {
690 FOR_EACH_OBSERVER(
691 EasyUnlockServiceObserver, observers_, OnTurnOffOperationStatusChanged());
694 void EasyUnlockService::ResetScreenlockState() {
695 screenlock_state_handler_.reset();
696 auth_attempt_.reset();
699 void EasyUnlockService::SetScreenlockHardlockedState(
700 EasyUnlockScreenlockStateHandler::HardlockState state) {
701 if (screenlock_state_handler_)
702 screenlock_state_handler_->SetHardlockState(state);
703 if (state != EasyUnlockScreenlockStateHandler::NO_HARDLOCK)
704 auth_attempt_.reset();
707 void EasyUnlockService::InitializeOnAppManagerReady() {
708 CHECK(app_manager_.get());
710 InitializeInternal();
711 bluetooth_detector_->Initialize();
714 void EasyUnlockService::OnBluetoothAdapterPresentChanged() {
715 UpdateAppState();
717 // Whether we've already passed Bluetooth availability information to UMA.
718 // This is static because there may be multiple instances and we want to
719 // report this system-level stat only once per run of Chrome.
720 static bool bluetooth_adapter_has_been_reported = false;
722 if (!bluetooth_adapter_has_been_reported) {
723 bluetooth_adapter_has_been_reported = true;
724 int bttype = BT_NO_ADAPTER;
725 if (bluetooth_detector_->IsPresent()) {
726 bttype = BT_LOW_ENERGY_CAPABLE;
727 #if defined(OS_WIN)
728 if (base::win::GetVersion() < base::win::VERSION_WIN8) {
729 bttype = BT_NORMAL;
731 #endif
733 UMA_HISTOGRAM_ENUMERATION(
734 "EasyUnlock.BluetoothAvailability", bttype, BT_MAX_TYPE);
738 void EasyUnlockService::SetHardlockStateForUser(
739 const std::string& user_id,
740 EasyUnlockScreenlockStateHandler::HardlockState state) {
741 DCHECK(!user_id.empty());
743 PrefService* local_state = GetLocalState();
744 if (!local_state)
745 return;
747 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
748 update->SetIntegerWithoutPathExpansion(user_id, static_cast<int>(state));
750 if (GetUserEmail() == user_id)
751 SetScreenlockHardlockedState(state);
754 EasyUnlockAuthEvent EasyUnlockService::GetPasswordAuthEvent() const {
755 DCHECK(IsEnabled());
757 if (GetHardlockState() != EasyUnlockScreenlockStateHandler::NO_HARDLOCK) {
758 switch (GetHardlockState()) {
759 case EasyUnlockScreenlockStateHandler::NO_HARDLOCK:
760 NOTREACHED();
761 return EASY_UNLOCK_AUTH_EVENT_COUNT;
762 case EasyUnlockScreenlockStateHandler::NO_PAIRING:
763 return PASSWORD_ENTRY_NO_PAIRING;
764 case EasyUnlockScreenlockStateHandler::USER_HARDLOCK:
765 return PASSWORD_ENTRY_USER_HARDLOCK;
766 case EasyUnlockScreenlockStateHandler::PAIRING_CHANGED:
767 return PASSWORD_ENTRY_PAIRING_CHANGED;
768 case EasyUnlockScreenlockStateHandler::LOGIN_FAILED:
769 return PASSWORD_ENTRY_LOGIN_FAILED;
770 case EasyUnlockScreenlockStateHandler::PAIRING_ADDED:
771 return PASSWORD_ENTRY_PAIRING_ADDED;
773 } else if (!screenlock_state_handler()) {
774 return PASSWORD_ENTRY_NO_SCREENLOCK_STATE_HANDLER;
775 } else {
776 switch (screenlock_state_handler()->state()) {
777 case EasyUnlockScreenlockStateHandler::STATE_INACTIVE:
778 return PASSWORD_ENTRY_SERVICE_NOT_ACTIVE;
779 case EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH:
780 return PASSWORD_ENTRY_NO_BLUETOOTH;
781 case EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING:
782 return PASSWORD_ENTRY_BLUETOOTH_CONNECTING;
783 case EasyUnlockScreenlockStateHandler::STATE_NO_PHONE:
784 return PASSWORD_ENTRY_NO_PHONE;
785 case EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED:
786 return PASSWORD_ENTRY_PHONE_NOT_AUTHENTICATED;
787 case EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED:
788 return PASSWORD_ENTRY_PHONE_LOCKED;
789 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE:
790 return PASSWORD_ENTRY_PHONE_NOT_LOCKABLE;
791 case EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED:
792 return PASSWORD_ENTRY_PHONE_UNSUPPORTED;
793 case EasyUnlockScreenlockStateHandler::STATE_RSSI_TOO_LOW:
794 return PASSWORD_ENTRY_RSSI_TOO_LOW;
795 case EasyUnlockScreenlockStateHandler::STATE_TX_POWER_TOO_HIGH:
796 return PASSWORD_ENTRY_TX_POWER_TOO_HIGH;
797 case EasyUnlockScreenlockStateHandler::
798 STATE_PHONE_LOCKED_AND_TX_POWER_TOO_HIGH:
799 return PASSWORD_ENTRY_PHONE_LOCKED_AND_TX_POWER_TOO_HIGH;
800 case EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED:
801 return PASSWORD_ENTRY_WITH_AUTHENTICATED_PHONE;
805 NOTREACHED();
806 return EASY_UNLOCK_AUTH_EVENT_COUNT;
809 #if defined(OS_CHROMEOS)
810 void EasyUnlockService::OnCryptohomeKeysFetchedForChecking(
811 const std::string& user_id,
812 const std::set<std::string> paired_devices,
813 bool success,
814 const chromeos::EasyUnlockDeviceKeyDataList& key_data_list) {
815 DCHECK(!user_id.empty() && !paired_devices.empty());
817 if (!success) {
818 SetHardlockStateForUser(user_id,
819 EasyUnlockScreenlockStateHandler::NO_PAIRING);
820 return;
823 std::set<std::string> devices_in_cryptohome;
824 for (const auto& device_key_data : key_data_list)
825 devices_in_cryptohome.insert(device_key_data.psk);
827 if (paired_devices != devices_in_cryptohome ||
828 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING) {
829 SetHardlockStateForUser(
830 user_id,
831 devices_in_cryptohome.empty()
832 ? EasyUnlockScreenlockStateHandler::PAIRING_ADDED
833 : EasyUnlockScreenlockStateHandler::PAIRING_CHANGED);
836 #endif
838 void EasyUnlockService::PrepareForSuspend() {
839 app_manager_->DisableAppIfLoaded();
840 if (screenlock_state_handler_ && screenlock_state_handler_->IsActive()) {
841 UpdateScreenlockState(
842 EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING);
846 void EasyUnlockService::EnsureTpmKeyPresentIfNeeded() {
847 if (tpm_key_checked_ || GetType() != TYPE_REGULAR || GetUserEmail().empty())
848 return;
850 #if defined(OS_CHROMEOS)
851 // If this is called before the session is started, the chances are Chrome
852 // is restarting in order to apply user flags. Don't check TPM keys in this
853 // case.
854 if (!user_manager::UserManager::Get() ||
855 !user_manager::UserManager::Get()->IsSessionStarted())
856 return;
858 // TODO(tbarzic): Set check_private_key only if previous sign-in attempt
859 // failed.
860 EasyUnlockTpmKeyManagerFactory::GetInstance()->Get(profile_)
861 ->PrepareTpmKey(true /* check_private_key */,
862 base::Closure());
863 #endif // defined(OS_CHROMEOS)
865 tpm_key_checked_ = true;