Allow only one bookmark to be added for multiple fast starring
[chromium-blink-merge.git] / chrome / browser / signin / easy_unlock_service.cc
blobc8c19cfbf35cb05bb079701623a9d87645ea0202
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/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"
60 #endif
62 #if defined(OS_WIN)
63 #include "base/win/windows_version.h"
64 #endif
66 using proximity_auth::ScreenlockState;
68 namespace {
70 enum BluetoothType {
71 BT_NO_ADAPTER,
72 BT_NORMAL,
73 BT_LOW_ENERGY_CAPABLE,
74 BT_MAX_TYPE
77 PrefService* GetLocalState() {
78 return g_browser_process ? g_browser_process->local_state() : NULL;
81 } // namespace
83 EasyUnlockService::UserSettings::UserSettings()
84 : require_close_proximity(false) {
87 EasyUnlockService::UserSettings::~UserSettings() {
90 // static
91 EasyUnlockService* EasyUnlockService::Get(Profile* profile) {
92 return EasyUnlockServiceFactory::GetForBrowserContext(profile);
95 // static
96 EasyUnlockService* EasyUnlockService::GetForUser(
97 const user_manager::User& user) {
98 #if defined(OS_CHROMEOS)
99 Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(&user);
100 if (!profile)
101 return NULL;
102 return EasyUnlockService::Get(profile);
103 #else
104 return NULL;
105 #endif
108 // static
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 {
117 public:
118 explicit BluetoothDetector(EasyUnlockService* service)
119 : service_(service),
120 weak_ptr_factory_(this) {
121 apps::AppLifetimeMonitorFactory::GetForProfile(service_->profile())
122 ->AddObserver(this);
125 ~BluetoothDetector() override {
126 if (adapter_.get())
127 adapter_->RemoveObserver(this);
128 apps::AppLifetimeMonitorFactory::GetForProfile(service_->profile())
129 ->RemoveObserver(this);
132 void Initialize() {
133 if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
134 return;
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();
153 private:
154 void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter) {
155 adapter_ = 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);
167 adapter_ = NULL;
168 #else
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() {
191 if (adapter_) {
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 {
208 public:
209 explicit PowerMonitor(EasyUnlockService* service)
210 : service_(service),
211 waking_up_(false),
212 weak_ptr_factory_(this) {
213 chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
214 AddObserver(this);
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())
227 return;
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_; }
236 private:
237 // chromeos::PowerManagerClient::Observer:
238 void SuspendImminent() override { service_->PrepareForSuspend(); }
240 void SuspendDone(const base::TimeDelta& sleep_duration) override {
241 waking_up_ = true;
242 wake_up_time_ = base::Time::Now();
243 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
244 FROM_HERE,
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() {
254 waking_up_ = false;
255 service_->UpdateAppState();
258 EasyUnlockService* service_;
259 bool waking_up_;
260 base::Time wake_up_time_;
261 base::WeakPtrFactory<PowerMonitor> weak_ptr_factory_;
263 DISALLOW_COPY_AND_ASSIGN(PowerMonitor);
265 #endif
267 EasyUnlockService::EasyUnlockService(Profile* profile)
268 : profile_(profile),
269 proximity_auth_client_(profile),
270 bluetooth_detector_(new BluetoothDetector(this)),
271 shut_down_(false),
272 tpm_key_checked_(false),
273 weak_ptr_factory_(this) {
276 EasyUnlockService::~EasyUnlockService() {
279 // static
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,
288 false,
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);
300 // static
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);
307 #endif
310 // static
311 void EasyUnlockService::ResetLocalStateForUser(const std::string& user_id) {
312 DCHECK(!user_id.empty());
314 PrefService* local_state = GetLocalState();
315 if (!local_state)
316 return;
318 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
319 update->RemoveWithoutPathExpansion(user_id, NULL);
321 #if defined(OS_CHROMEOS)
322 EasyUnlockTpmKeyManager::ResetLocalStateForUser(user_id);
323 #endif
326 // static
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();
333 if (!local_state)
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,
343 &user_prefs_dict))
344 return user_settings;
346 user_prefs_dict->GetBooleanWithoutPathExpansion(
347 prefs::kEasyUnlockProximityRequired,
348 &user_settings.require_close_proximity);
350 return user_settings;
353 // static
354 std::string EasyUnlockService::GetDeviceId() {
355 PrefService* local_state = GetLocalState();
356 if (!local_state)
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);
364 return 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 {
376 if (shut_down_)
377 return false;
379 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
380 proximity_auth::switches::kDisableEasyUnlock)) {
381 return false;
384 if (!IsAllowedInternal())
385 return false;
387 #if defined(OS_CHROMEOS)
388 if (!bluetooth_detector_->IsPresent())
389 return false;
391 return true;
392 #else
393 // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
394 return false;
395 #endif
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();
411 if (user_id.empty())
412 return;
414 if (state == GetHardlockState())
415 return;
417 SetHardlockStateForUser(user_id, state);
420 EasyUnlockScreenlockStateHandler::HardlockState
421 EasyUnlockService::GetHardlockState() const {
422 EasyUnlockScreenlockStateHandler::HardlockState state;
423 if (GetPersistedHardlockState(&state))
424 return state;
426 return EasyUnlockScreenlockStateHandler::NO_HARDLOCK;
429 bool EasyUnlockService::GetPersistedHardlockState(
430 EasyUnlockScreenlockStateHandler::HardlockState* state) const {
431 std::string user_id = GetUserEmail();
432 if (user_id.empty())
433 return false;
435 PrefService* local_state = GetLocalState();
436 if (!local_state)
437 return false;
439 const base::DictionaryValue* dict =
440 local_state->GetDictionary(prefs::kEasyUnlockHardlockState);
441 int state_int;
442 if (dict && dict->GetIntegerWithoutPathExpansion(user_id, &state_int)) {
443 *state =
444 static_cast<EasyUnlockScreenlockStateHandler::HardlockState>(state_int);
445 return true;
448 return false;
451 void EasyUnlockService::ShowInitialUserState() {
452 if (!GetScreenlockStateHandler())
453 return;
455 EasyUnlockScreenlockStateHandler::HardlockState state;
456 bool has_persisted_state = GetPersistedHardlockState(&state);
457 if (!has_persisted_state)
458 return;
460 if (state == EasyUnlockScreenlockStateHandler::NO_HARDLOCK) {
461 // Show connecting icon early when there is a persisted non hardlock state.
462 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING);
463 } else {
464 screenlock_state_handler_->MaybeShowHardlockUI();
468 EasyUnlockScreenlockStateHandler*
469 EasyUnlockService::GetScreenlockStateHandler() {
470 if (!IsAllowed())
471 return NULL;
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();
482 if (!handler)
483 return false;
485 handler->ChangeState(state);
487 if (state == ScreenlockState::AUTHENTICATED) {
488 #if defined(OS_CHROMEOS)
489 if (power_monitor_)
490 power_monitor_->RecordStartUpTime();
491 #endif
492 } else if (auth_attempt_.get()) {
493 // Clean up existing auth attempt if we can no longer authenticate the
494 // remote device.
495 auth_attempt_.reset();
497 if (!handler->InStateValidOnRemoteAuthFailure())
498 HandleAuthFailure(GetUserEmail());
501 FOR_EACH_OBSERVER(
502 EasyUnlockServiceObserver, observers_, OnScreenlockStateChanged(state));
503 return true;
506 ScreenlockState EasyUnlockService::GetScreenlockState() {
507 EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
508 if (!handler)
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(),
529 std::string());
531 return;
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();
542 void EasyUnlockService::FinalizeUnlock(bool success) {
543 if (!auth_attempt_.get())
544 return;
546 this->OnWillFinalizeUnlock(success);
547 auth_attempt_->FinalizeUnlock(GetUserEmail(), success);
548 auth_attempt_.reset();
549 // TODO(isherman): If observing screen unlock events, is there a race
550 // condition in terms of reading the service's state vs. the app setting the
551 // state?
553 // Make sure that the lock screen is updated on failure.
554 if (!success) {
555 RecordEasyUnlockScreenUnlockEvent(EASY_UNLOCK_FAILURE);
556 HandleAuthFailure(GetUserEmail());
560 void EasyUnlockService::FinalizeSignin(const std::string& key) {
561 if (!auth_attempt_.get())
562 return;
563 std::string wrapped_secret = GetWrappedSecret();
564 if (!wrapped_secret.empty())
565 auth_attempt_->FinalizeSignin(GetUserEmail(), wrapped_secret, key);
566 auth_attempt_.reset();
568 // Processing empty key is equivalent to auth cancellation. In this case the
569 // signin request will not actually be processed by login stack, so the lock
570 // screen state should be set from here.
571 if (key.empty())
572 HandleAuthFailure(GetUserEmail());
575 void EasyUnlockService::HandleAuthFailure(const std::string& user_id) {
576 if (user_id != GetUserEmail())
577 return;
579 if (!screenlock_state_handler_.get())
580 return;
582 screenlock_state_handler_->SetHardlockState(
583 EasyUnlockScreenlockStateHandler::LOGIN_FAILED);
586 void EasyUnlockService::CheckCryptohomeKeysAndMaybeHardlock() {
587 #if defined(OS_CHROMEOS)
588 std::string user_id = GetUserEmail();
589 if (user_id.empty())
590 return;
592 const base::ListValue* device_list = GetRemoteDevices();
593 std::set<std::string> paired_devices;
594 if (device_list) {
595 chromeos::EasyUnlockDeviceKeyDataList parsed_paired;
596 chromeos::EasyUnlockKeyManager::RemoteDeviceListToDeviceDataList(
597 *device_list, &parsed_paired);
598 for (const auto& device_key_data : parsed_paired)
599 paired_devices.insert(device_key_data.psk);
601 if (paired_devices.empty()) {
602 SetHardlockState(EasyUnlockScreenlockStateHandler::NO_PAIRING);
603 return;
606 // No need to compare if a change is already recorded.
607 if (GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_CHANGED ||
608 GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_ADDED) {
609 return;
612 chromeos::EasyUnlockKeyManager* key_manager =
613 chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager();
614 DCHECK(key_manager);
616 key_manager->GetDeviceDataList(
617 chromeos::UserContext(user_id),
618 base::Bind(&EasyUnlockService::OnCryptohomeKeysFetchedForChecking,
619 weak_ptr_factory_.GetWeakPtr(),
620 user_id,
621 paired_devices));
622 #endif
625 void EasyUnlockService::SetTrialRun() {
626 DCHECK_EQ(GetType(), TYPE_REGULAR);
628 EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
629 if (handler)
630 handler->SetTrialRun();
633 void EasyUnlockService::RecordClickOnLockIcon() {
634 if (screenlock_state_handler_)
635 screenlock_state_handler_->RecordClickOnLockIcon();
638 void EasyUnlockService::AddObserver(EasyUnlockServiceObserver* observer) {
639 observers_.AddObserver(observer);
642 void EasyUnlockService::RemoveObserver(EasyUnlockServiceObserver* observer) {
643 observers_.RemoveObserver(observer);
646 PrefService* EasyUnlockService::GetPrefService() {
647 return profile()->GetPrefs();
650 scoped_ptr<proximity_auth::SecureMessageDelegate>
651 EasyUnlockService::CreateSecureMessageDelegate() {
652 #if defined(OS_CHROMEOS)
653 return make_scoped_ptr(new chromeos::SecureMessageDelegateChromeOS());
654 #else
655 return nullptr;
656 #endif
659 scoped_ptr<proximity_auth::CryptAuthClientFactory>
660 EasyUnlockService::CreateCryptAuthClientFactory() {
661 return make_scoped_ptr(new proximity_auth::CryptAuthClientFactoryImpl(
662 ProfileOAuth2TokenServiceFactory::GetForProfile(profile()),
663 SigninManagerFactory::GetForProfile(profile())
664 ->GetAuthenticatedAccountId(),
665 profile()->GetRequestContext(), GetDeviceClassifier()));
668 cryptauth::DeviceClassifier EasyUnlockService::GetDeviceClassifier() {
669 cryptauth::DeviceClassifier device_classifier;
671 #if defined(OS_CHROMEOS)
672 int32 major_version, minor_version, bugfix_version;
673 // TODO(tengs): base::OperatingSystemVersionNumbers only works for ChromeOS.
674 // We need to get different numbers for other platforms.
675 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
676 &bugfix_version);
677 device_classifier.set_device_os_version_code(major_version);
678 device_classifier.set_device_type(cryptauth::CHROME);
679 #endif
681 const std::vector<uint32_t>& version_components =
682 base::Version(version_info::GetVersionNumber()).components();
683 if (version_components.size() > 0)
684 device_classifier.set_device_software_version_code(version_components[0]);
686 device_classifier.set_device_software_package(version_info::GetProductName());
687 return device_classifier;
690 std::string EasyUnlockService::GetAccountId() {
691 return SigninManagerFactory::GetForProfile(profile())
692 ->GetAuthenticatedAccountId();
695 gcm::GCMDriver* EasyUnlockService::GetGCMDriver() {
696 gcm::GCMProfileService* gcm_profile_service =
697 gcm::GCMProfileServiceFactory::GetForProfile(profile_);
698 return gcm_profile_service->driver();
701 void EasyUnlockService::Shutdown() {
702 if (shut_down_)
703 return;
704 shut_down_ = true;
706 ShutdownInternal();
708 ResetScreenlockState();
709 bluetooth_detector_.reset();
710 #if defined(OS_CHROMEOS)
711 power_monitor_.reset();
712 #endif
714 weak_ptr_factory_.InvalidateWeakPtrs();
717 void EasyUnlockService::ReloadAppAndLockScreen() {
718 // Make sure lock screen state set by the extension gets reset.
719 ResetScreenlockState();
720 app_manager_->ReloadApp();
721 NotifyUserUpdated();
724 void EasyUnlockService::UpdateAppState() {
725 if (IsAllowed()) {
726 EnsureTpmKeyPresentIfNeeded();
727 app_manager_->LoadApp();
728 NotifyUserUpdated();
730 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
731 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery) &&
732 GetType() == EasyUnlockService::TYPE_REGULAR &&
733 !proximity_auth_ble_system_) {
734 proximity_auth_ble_system_.reset(
735 new proximity_auth::ProximityAuthBleSystem(
736 proximity_auth::ScreenlockBridge::Get(), &proximity_auth_client_,
737 CreateCryptAuthClientFactory(), profile_->GetPrefs()));
740 #if defined(OS_CHROMEOS)
741 if (!power_monitor_)
742 power_monitor_.reset(new PowerMonitor(this));
743 #endif
744 } else {
745 bool bluetooth_waking_up = false;
746 #if defined(OS_CHROMEOS)
747 // If the service is not allowed due to bluetooth not being detected just
748 // after system suspend is done, give bluetooth more time to be detected
749 // before disabling the app (and resetting screenlock state).
750 bluetooth_waking_up =
751 power_monitor_.get() && power_monitor_->waking_up() &&
752 !bluetooth_detector_->IsPresent();
753 #endif
755 if (!bluetooth_waking_up) {
756 app_manager_->DisableAppIfLoaded();
757 ResetScreenlockState();
758 proximity_auth_ble_system_.reset();
759 #if defined(OS_CHROMEOS)
760 power_monitor_.reset();
761 #endif
766 void EasyUnlockService::DisableAppWithoutResettingScreenlockState() {
767 app_manager_->DisableAppIfLoaded();
770 void EasyUnlockService::NotifyUserUpdated() {
771 std::string user_id = GetUserEmail();
772 if (user_id.empty())
773 return;
775 // Notify the easy unlock app that the user info changed.
776 bool logged_in = GetType() == TYPE_REGULAR;
777 bool data_ready = logged_in || GetRemoteDevices() != NULL;
778 app_manager_->SendUserUpdatedEvent(user_id, logged_in, data_ready);
781 void EasyUnlockService::NotifyTurnOffOperationStatusChanged() {
782 FOR_EACH_OBSERVER(
783 EasyUnlockServiceObserver, observers_, OnTurnOffOperationStatusChanged());
786 void EasyUnlockService::ResetScreenlockState() {
787 screenlock_state_handler_.reset();
788 auth_attempt_.reset();
791 void EasyUnlockService::SetScreenlockHardlockedState(
792 EasyUnlockScreenlockStateHandler::HardlockState state) {
793 if (screenlock_state_handler_)
794 screenlock_state_handler_->SetHardlockState(state);
795 if (state != EasyUnlockScreenlockStateHandler::NO_HARDLOCK)
796 auth_attempt_.reset();
799 void EasyUnlockService::InitializeOnAppManagerReady() {
800 CHECK(app_manager_.get());
802 InitializeInternal();
803 bluetooth_detector_->Initialize();
806 void EasyUnlockService::OnBluetoothAdapterPresentChanged() {
807 UpdateAppState();
809 // Whether we've already passed Bluetooth availability information to UMA.
810 // This is static because there may be multiple instances and we want to
811 // report this system-level stat only once per run of Chrome.
812 static bool bluetooth_adapter_has_been_reported = false;
814 if (!bluetooth_adapter_has_been_reported) {
815 bluetooth_adapter_has_been_reported = true;
816 int bttype = BT_NO_ADAPTER;
817 if (bluetooth_detector_->IsPresent()) {
818 bttype = BT_LOW_ENERGY_CAPABLE;
819 #if defined(OS_WIN)
820 if (base::win::GetVersion() < base::win::VERSION_WIN8) {
821 bttype = BT_NORMAL;
823 #endif
825 UMA_HISTOGRAM_ENUMERATION(
826 "EasyUnlock.BluetoothAvailability", bttype, BT_MAX_TYPE);
830 void EasyUnlockService::SetHardlockStateForUser(
831 const std::string& user_id,
832 EasyUnlockScreenlockStateHandler::HardlockState state) {
833 DCHECK(!user_id.empty());
835 PrefService* local_state = GetLocalState();
836 if (!local_state)
837 return;
839 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
840 update->SetIntegerWithoutPathExpansion(user_id, static_cast<int>(state));
842 if (GetUserEmail() == user_id)
843 SetScreenlockHardlockedState(state);
846 EasyUnlockAuthEvent EasyUnlockService::GetPasswordAuthEvent() const {
847 DCHECK(IsEnabled());
849 if (GetHardlockState() != EasyUnlockScreenlockStateHandler::NO_HARDLOCK) {
850 switch (GetHardlockState()) {
851 case EasyUnlockScreenlockStateHandler::NO_HARDLOCK:
852 NOTREACHED();
853 return EASY_UNLOCK_AUTH_EVENT_COUNT;
854 case EasyUnlockScreenlockStateHandler::NO_PAIRING:
855 return PASSWORD_ENTRY_NO_PAIRING;
856 case EasyUnlockScreenlockStateHandler::USER_HARDLOCK:
857 return PASSWORD_ENTRY_USER_HARDLOCK;
858 case EasyUnlockScreenlockStateHandler::PAIRING_CHANGED:
859 return PASSWORD_ENTRY_PAIRING_CHANGED;
860 case EasyUnlockScreenlockStateHandler::LOGIN_FAILED:
861 return PASSWORD_ENTRY_LOGIN_FAILED;
862 case EasyUnlockScreenlockStateHandler::PAIRING_ADDED:
863 return PASSWORD_ENTRY_PAIRING_ADDED;
865 } else if (!screenlock_state_handler()) {
866 return PASSWORD_ENTRY_NO_SCREENLOCK_STATE_HANDLER;
867 } else {
868 switch (screenlock_state_handler()->state()) {
869 case ScreenlockState::INACTIVE:
870 return PASSWORD_ENTRY_SERVICE_NOT_ACTIVE;
871 case ScreenlockState::NO_BLUETOOTH:
872 return PASSWORD_ENTRY_NO_BLUETOOTH;
873 case ScreenlockState::BLUETOOTH_CONNECTING:
874 return PASSWORD_ENTRY_BLUETOOTH_CONNECTING;
875 case ScreenlockState::NO_PHONE:
876 return PASSWORD_ENTRY_NO_PHONE;
877 case ScreenlockState::PHONE_NOT_AUTHENTICATED:
878 return PASSWORD_ENTRY_PHONE_NOT_AUTHENTICATED;
879 case ScreenlockState::PHONE_LOCKED:
880 return PASSWORD_ENTRY_PHONE_LOCKED;
881 case ScreenlockState::PHONE_NOT_LOCKABLE:
882 return PASSWORD_ENTRY_PHONE_NOT_LOCKABLE;
883 case ScreenlockState::PHONE_UNSUPPORTED:
884 return PASSWORD_ENTRY_PHONE_UNSUPPORTED;
885 case ScreenlockState::RSSI_TOO_LOW:
886 return PASSWORD_ENTRY_RSSI_TOO_LOW;
887 case ScreenlockState::TX_POWER_TOO_HIGH:
888 return PASSWORD_ENTRY_TX_POWER_TOO_HIGH;
889 case ScreenlockState::PHONE_LOCKED_AND_TX_POWER_TOO_HIGH:
890 return PASSWORD_ENTRY_PHONE_LOCKED_AND_TX_POWER_TOO_HIGH;
891 case ScreenlockState::AUTHENTICATED:
892 return PASSWORD_ENTRY_WITH_AUTHENTICATED_PHONE;
896 NOTREACHED();
897 return EASY_UNLOCK_AUTH_EVENT_COUNT;
900 #if defined(OS_CHROMEOS)
901 void EasyUnlockService::OnCryptohomeKeysFetchedForChecking(
902 const std::string& user_id,
903 const std::set<std::string> paired_devices,
904 bool success,
905 const chromeos::EasyUnlockDeviceKeyDataList& key_data_list) {
906 DCHECK(!user_id.empty() && !paired_devices.empty());
908 if (!success) {
909 SetHardlockStateForUser(user_id,
910 EasyUnlockScreenlockStateHandler::NO_PAIRING);
911 return;
914 std::set<std::string> devices_in_cryptohome;
915 for (const auto& device_key_data : key_data_list)
916 devices_in_cryptohome.insert(device_key_data.psk);
918 if (paired_devices != devices_in_cryptohome ||
919 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING) {
920 SetHardlockStateForUser(
921 user_id,
922 devices_in_cryptohome.empty()
923 ? EasyUnlockScreenlockStateHandler::PAIRING_ADDED
924 : EasyUnlockScreenlockStateHandler::PAIRING_CHANGED);
927 #endif
929 void EasyUnlockService::PrepareForSuspend() {
930 app_manager_->DisableAppIfLoaded();
931 if (screenlock_state_handler_ && screenlock_state_handler_->IsActive())
932 UpdateScreenlockState(ScreenlockState::BLUETOOTH_CONNECTING);
935 void EasyUnlockService::EnsureTpmKeyPresentIfNeeded() {
936 if (tpm_key_checked_ || GetType() != TYPE_REGULAR || GetUserEmail().empty() ||
937 GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING) {
938 return;
941 #if defined(OS_CHROMEOS)
942 // If this is called before the session is started, the chances are Chrome
943 // is restarting in order to apply user flags. Don't check TPM keys in this
944 // case.
945 if (!user_manager::UserManager::Get() ||
946 !user_manager::UserManager::Get()->IsSessionStarted())
947 return;
949 // TODO(tbarzic): Set check_private_key only if previous sign-in attempt
950 // failed.
951 EasyUnlockTpmKeyManagerFactory::GetInstance()->Get(profile_)
952 ->PrepareTpmKey(true /* check_private_key */,
953 base::Closure());
954 #endif // defined(OS_CHROMEOS)
956 tpm_key_checked_ = true;