Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / signin / easy_unlock_service.cc
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.
4
5 #include "chrome/browser/signin/easy_unlock_service.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/prefs/pref_registry_simple.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/prefs/scoped_user_pref_update.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "base/time/time.h"
16 #include "base/values.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/extensions/component_loader.h"
19 #include "chrome/browser/extensions/extension_service.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/signin/easy_unlock_auth_attempt.h"
22 #include "chrome/browser/signin/easy_unlock_service_factory.h"
23 #include "chrome/browser/signin/easy_unlock_service_observer.h"
24 #include "chrome/browser/signin/screenlock_bridge.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/extensions/api/easy_unlock_private.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/user_manager/user.h"
31 #include "device/bluetooth/bluetooth_adapter.h"
32 #include "device/bluetooth/bluetooth_adapter_factory.h"
33 #include "extensions/browser/event_router.h"
34 #include "extensions/browser/extension_registry.h"
35 #include "extensions/browser/extension_system.h"
36 #include "extensions/common/one_shot_event.h"
37 #include "grit/browser_resources.h"
38
39 #if defined(OS_CHROMEOS)
40 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
41 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
42 #include "chrome/browser/chromeos/profiles/profile_helper.h"
43 #include "chromeos/chromeos_switches.h"
44 #include "chromeos/dbus/dbus_thread_manager.h"
45 #include "chromeos/dbus/power_manager_client.h"
46 #endif
47
48 namespace {
49
50 extensions::ComponentLoader* GetComponentLoader(
51     content::BrowserContext* context) {
52   extensions::ExtensionSystem* extension_system =
53       extensions::ExtensionSystem::Get(context);
54   ExtensionService* extension_service = extension_system->extension_service();
55   return extension_service->component_loader();
56 }
57
58 PrefService* GetLocalState() {
59   return g_browser_process ? g_browser_process->local_state() : NULL;
60 }
61
62 }  // namespace
63
64 // static
65 EasyUnlockService* EasyUnlockService::Get(Profile* profile) {
66   return EasyUnlockServiceFactory::GetForProfile(profile);
67 }
68
69 // static
70 EasyUnlockService* EasyUnlockService::GetForUser(
71     const user_manager::User& user) {
72 #if defined(OS_CHROMEOS)
73   Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(&user);
74   if (!profile)
75     return NULL;
76   return EasyUnlockService::Get(profile);
77 #else
78   return NULL;
79 #endif
80 }
81
82 // static
83 bool EasyUnlockService::IsSignInEnabled() {
84 #if defined(OS_CHROMEOS)
85   const std::string group_name =
86       base::FieldTrialList::FindFullName("EasySignIn");
87
88   if (CommandLine::ForCurrentProcess()->HasSwitch(
89           chromeos::switches::kDisableEasySignin)) {
90     return false;
91   }
92
93   return group_name == "Enable";
94 #else
95   return false;
96 #endif
97 }
98
99 class EasyUnlockService::BluetoothDetector
100     : public device::BluetoothAdapter::Observer {
101  public:
102   explicit BluetoothDetector(EasyUnlockService* service)
103       : service_(service),
104         weak_ptr_factory_(this) {
105   }
106
107   ~BluetoothDetector() override {
108     if (adapter_.get())
109       adapter_->RemoveObserver(this);
110   }
111
112   void Initialize() {
113     if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
114       return;
115
116     device::BluetoothAdapterFactory::GetAdapter(
117         base::Bind(&BluetoothDetector::OnAdapterInitialized,
118                    weak_ptr_factory_.GetWeakPtr()));
119   }
120
121   bool IsPresent() const { return adapter_.get() && adapter_->IsPresent(); }
122
123   // device::BluetoothAdapter::Observer:
124   void AdapterPresentChanged(device::BluetoothAdapter* adapter,
125                              bool present) override {
126     service_->OnBluetoothAdapterPresentChanged();
127   }
128
129  private:
130   void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter) {
131     adapter_ = adapter;
132     adapter_->AddObserver(this);
133     service_->OnBluetoothAdapterPresentChanged();
134   }
135
136   // Owner of this class and should out-live this class.
137   EasyUnlockService* service_;
138   scoped_refptr<device::BluetoothAdapter> adapter_;
139   base::WeakPtrFactory<BluetoothDetector> weak_ptr_factory_;
140
141   DISALLOW_COPY_AND_ASSIGN(BluetoothDetector);
142 };
143
144 #if defined(OS_CHROMEOS)
145 class EasyUnlockService::PowerMonitor
146     : public chromeos::PowerManagerClient::Observer {
147  public:
148   explicit PowerMonitor(EasyUnlockService* service)
149       : service_(service),
150         waking_up_(false),
151         weak_ptr_factory_(this) {
152     chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
153         AddObserver(this);
154   }
155
156   virtual ~PowerMonitor() {
157     chromeos::DBusThreadManager::Get()->GetPowerManagerClient()->
158         RemoveObserver(this);
159   }
160
161   bool waking_up() const { return waking_up_; }
162
163  private:
164   // chromeos::PowerManagerClient::Observer:
165   virtual void SuspendImminent() override {
166     service_->PrepareForSuspend();
167   }
168
169   virtual void SuspendDone(const base::TimeDelta& sleep_duration) override {
170     waking_up_ = true;
171     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
172         FROM_HERE,
173         base::Bind(&PowerMonitor::ResetWakingUp,
174                    weak_ptr_factory_.GetWeakPtr()),
175         base::TimeDelta::FromSeconds(5));
176     service_->UpdateAppState();
177     // Note that |this| may get deleted after |UpdateAppState| is called.
178   }
179
180   void ResetWakingUp() {
181     waking_up_ = false;
182     service_->UpdateAppState();
183   }
184
185   EasyUnlockService* service_;
186   bool waking_up_;
187   base::WeakPtrFactory<PowerMonitor> weak_ptr_factory_;
188
189   DISALLOW_COPY_AND_ASSIGN(PowerMonitor);
190 };
191 #endif
192
193 EasyUnlockService::EasyUnlockService(Profile* profile)
194     : profile_(profile),
195       bluetooth_detector_(new BluetoothDetector(this)),
196       shut_down_(false),
197       weak_ptr_factory_(this) {
198   extensions::ExtensionSystem::Get(profile_)->ready().Post(
199       FROM_HERE,
200       base::Bind(&EasyUnlockService::Initialize,
201                  weak_ptr_factory_.GetWeakPtr()));
202 }
203
204 EasyUnlockService::~EasyUnlockService() {
205 }
206
207 // static
208 void EasyUnlockService::RegisterProfilePrefs(
209     user_prefs::PrefRegistrySyncable* registry) {
210   registry->RegisterBooleanPref(
211       prefs::kEasyUnlockAllowed,
212       true,
213       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
214   registry->RegisterBooleanPref(
215       prefs::kEasyUnlockEnabled,
216       false,
217       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
218   registry->RegisterDictionaryPref(
219       prefs::kEasyUnlockPairing,
220       new base::DictionaryValue(),
221       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
222   registry->RegisterBooleanPref(
223       prefs::kEasyUnlockProximityRequired,
224       false,
225       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
226 }
227
228 // static
229 void EasyUnlockService::RegisterPrefs(PrefRegistrySimple* registry) {
230   registry->RegisterDictionaryPref(prefs::kEasyUnlockHardlockState);
231 }
232
233 // static
234 void EasyUnlockService::ResetLocalStateForUser(const std::string& user_id) {
235   DCHECK(!user_id.empty());
236
237   PrefService* local_state = GetLocalState();
238   if (!local_state)
239     return;
240
241   DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
242   update->RemoveWithoutPathExpansion(user_id, NULL);
243 }
244
245 bool EasyUnlockService::IsAllowed() {
246   if (shut_down_)
247     return false;
248
249   if (!IsAllowedInternal())
250     return false;
251
252 #if defined(OS_CHROMEOS)
253   if (!bluetooth_detector_->IsPresent())
254     return false;
255
256   return true;
257 #else
258   // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
259   return false;
260 #endif
261 }
262
263 void EasyUnlockService::SetHardlockState(
264     EasyUnlockScreenlockStateHandler::HardlockState state) {
265   const std::string user_id = GetUserEmail();
266   if (user_id.empty())
267     return;
268
269   SetHardlockStateForUser(user_id, state);
270 }
271
272 EasyUnlockScreenlockStateHandler::HardlockState
273 EasyUnlockService::GetHardlockState() const {
274   EasyUnlockScreenlockStateHandler::HardlockState state;
275   if (GetPersistedHardlockState(&state))
276     return state;
277
278   return EasyUnlockScreenlockStateHandler::NO_HARDLOCK;
279 }
280
281 bool EasyUnlockService::GetPersistedHardlockState(
282     EasyUnlockScreenlockStateHandler::HardlockState* state) const {
283   std::string user_id = GetUserEmail();
284   if (user_id.empty())
285     return false;
286
287   PrefService* local_state = GetLocalState();
288   if (!local_state)
289     return false;
290
291   const base::DictionaryValue* dict =
292       local_state->GetDictionary(prefs::kEasyUnlockHardlockState);
293   int state_int;
294   if (dict && dict->GetIntegerWithoutPathExpansion(user_id, &state_int)) {
295     *state =
296         static_cast<EasyUnlockScreenlockStateHandler::HardlockState>(state_int);
297     return true;
298   }
299
300   return false;
301 }
302
303 void EasyUnlockService::ShowInitialUserState() {
304   if (!GetScreenlockStateHandler())
305     return;
306
307   EasyUnlockScreenlockStateHandler::HardlockState state;
308   bool has_persisted_state = GetPersistedHardlockState(&state);
309   if (!has_persisted_state)
310     return;
311
312   if (state == EasyUnlockScreenlockStateHandler::NO_HARDLOCK) {
313     // Show connecting icon early when there is a persisted non hardlock state.
314     UpdateScreenlockState(
315         EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING);
316   } else {
317     screenlock_state_handler_->MaybeShowHardlockUI();
318   }
319 }
320
321 EasyUnlockScreenlockStateHandler*
322     EasyUnlockService::GetScreenlockStateHandler() {
323   if (!IsAllowed())
324     return NULL;
325   if (!screenlock_state_handler_) {
326     screenlock_state_handler_.reset(new EasyUnlockScreenlockStateHandler(
327         GetUserEmail(),
328         GetHardlockState(),
329         ScreenlockBridge::Get()));
330   }
331   return screenlock_state_handler_.get();
332 }
333
334 bool EasyUnlockService::UpdateScreenlockState(
335     EasyUnlockScreenlockStateHandler::State state) {
336   EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
337   if (!handler)
338     return false;
339
340   handler->ChangeState(state);
341
342   if (state != EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED &&
343       auth_attempt_.get()) {
344     auth_attempt_.reset();
345
346     if (!handler->InStateValidOnRemoteAuthFailure())
347       HandleAuthFailure(GetUserEmail());
348   }
349   return true;
350 }
351
352 void EasyUnlockService::AttemptAuth(const std::string& user_id) {
353   auth_attempt_.reset(new EasyUnlockAuthAttempt(
354       profile_,
355       GetUserEmail(),
356       GetType() == TYPE_REGULAR ? EasyUnlockAuthAttempt::TYPE_UNLOCK
357                                 : EasyUnlockAuthAttempt::TYPE_SIGNIN));
358   if (!auth_attempt_->Start(user_id))
359     auth_attempt_.reset();
360 }
361
362 void EasyUnlockService::FinalizeUnlock(bool success) {
363   if (!auth_attempt_.get())
364     return;
365
366   auth_attempt_->FinalizeUnlock(GetUserEmail(), success);
367   auth_attempt_.reset();
368
369   // Make sure that the lock screen is updated on failure.
370   if (!success)
371     HandleAuthFailure(GetUserEmail());
372 }
373
374 void EasyUnlockService::FinalizeSignin(const std::string& key) {
375   if (!auth_attempt_.get())
376     return;
377   std::string wrapped_secret = GetWrappedSecret();
378   if (!wrapped_secret.empty())
379     auth_attempt_->FinalizeSignin(GetUserEmail(), wrapped_secret, key);
380   auth_attempt_.reset();
381
382   // Processing empty key is equivalent to auth cancellation. In this case the
383   // signin request will not actually be processed by login stack, so the lock
384   // screen state should be set from here.
385   if (key.empty())
386     HandleAuthFailure(GetUserEmail());
387 }
388
389 void EasyUnlockService::HandleAuthFailure(const std::string& user_id) {
390   if (user_id != GetUserEmail())
391     return;
392
393   if (!screenlock_state_handler_.get())
394     return;
395
396   screenlock_state_handler_->SetHardlockState(
397       EasyUnlockScreenlockStateHandler::LOGIN_FAILED);
398 }
399
400 void EasyUnlockService::CheckCryptohomeKeysAndMaybeHardlock() {
401 #if defined(OS_CHROMEOS)
402   std::string user_id = GetUserEmail();
403   if (user_id.empty())
404     return;
405
406   const base::ListValue* device_list = GetRemoteDevices();
407   std::set<std::string> paired_devices;
408   if (device_list) {
409     chromeos::EasyUnlockDeviceKeyDataList parsed_paired;
410     chromeos::EasyUnlockKeyManager::RemoteDeviceListToDeviceDataList(
411         *device_list, &parsed_paired);
412     for (const auto& device_key_data : parsed_paired)
413       paired_devices.insert(device_key_data.psk);
414   }
415   if (paired_devices.empty()) {
416     SetHardlockState(EasyUnlockScreenlockStateHandler::NO_PAIRING);
417     return;
418   }
419
420   // No need to compare if a change is already recorded.
421   if (GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_CHANGED ||
422       GetHardlockState() == EasyUnlockScreenlockStateHandler::PAIRING_ADDED) {
423     return;
424   }
425
426   chromeos::EasyUnlockKeyManager* key_manager =
427       chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager();
428   DCHECK(key_manager);
429
430   key_manager->GetDeviceDataList(
431       chromeos::UserContext(user_id),
432       base::Bind(&EasyUnlockService::OnCryptohomeKeysFetchedForChecking,
433                  weak_ptr_factory_.GetWeakPtr(),
434                  user_id,
435                  paired_devices));
436 #endif
437 }
438
439 void EasyUnlockService::SetTrialRun() {
440   DCHECK(GetType() == TYPE_REGULAR);
441
442   EasyUnlockScreenlockStateHandler* handler = GetScreenlockStateHandler();
443   if (handler)
444     handler->SetTrialRun();
445 }
446
447 void EasyUnlockService::AddObserver(EasyUnlockServiceObserver* observer) {
448   observers_.AddObserver(observer);
449 }
450
451 void EasyUnlockService::RemoveObserver(EasyUnlockServiceObserver* observer) {
452   observers_.RemoveObserver(observer);
453 }
454
455 void  EasyUnlockService::Shutdown() {
456   if (shut_down_)
457     return;
458   shut_down_ = true;
459
460   ShutdownInternal();
461
462   weak_ptr_factory_.InvalidateWeakPtrs();
463
464   ResetScreenlockState();
465   bluetooth_detector_.reset();
466 #if defined(OS_CHROMEOS)
467   power_monitor_.reset();
468 #endif
469 }
470
471 void EasyUnlockService::LoadApp() {
472   DCHECK(IsAllowed());
473
474 #if defined(GOOGLE_CHROME_BUILD)
475   base::FilePath easy_unlock_path;
476 #if defined(OS_CHROMEOS)
477   easy_unlock_path = base::FilePath("/usr/share/chromeos-assets/easy_unlock");
478 #endif  // defined(OS_CHROMEOS)
479
480 #ifndef NDEBUG
481   // Only allow app path override switch for debug build.
482   const CommandLine* command_line = CommandLine::ForCurrentProcess();
483   if (command_line->HasSwitch(switches::kEasyUnlockAppPath)) {
484     easy_unlock_path =
485         command_line->GetSwitchValuePath(switches::kEasyUnlockAppPath);
486   }
487 #endif  // !defined(NDEBUG)
488
489   if (!easy_unlock_path.empty()) {
490     extensions::ComponentLoader* loader = GetComponentLoader(profile_);
491     if (!loader->Exists(extension_misc::kEasyUnlockAppId))
492       loader->Add(IDR_EASY_UNLOCK_MANIFEST, easy_unlock_path);
493
494     ExtensionService* extension_service =
495         extensions::ExtensionSystem::Get(profile_)->extension_service();
496     extension_service->EnableExtension(extension_misc::kEasyUnlockAppId);
497
498     NotifyUserUpdated();
499   }
500 #endif  // defined(GOOGLE_CHROME_BUILD)
501 }
502
503 void EasyUnlockService::DisableAppIfLoaded() {
504   extensions::ComponentLoader* loader = GetComponentLoader(profile_);
505   if (!loader->Exists(extension_misc::kEasyUnlockAppId))
506     return;
507
508   ExtensionService* extension_service =
509       extensions::ExtensionSystem::Get(profile_)->extension_service();
510   extension_service->DisableExtension(extension_misc::kEasyUnlockAppId,
511                                       extensions::Extension::DISABLE_RELOAD);
512 }
513
514 void EasyUnlockService::UnloadApp() {
515   GetComponentLoader(profile_)->Remove(extension_misc::kEasyUnlockAppId);
516 }
517
518 void EasyUnlockService::ReloadApp() {
519   // Make sure lock screen state set by the extension gets reset.
520   ResetScreenlockState();
521
522   if (!GetComponentLoader(profile_)->Exists(extension_misc::kEasyUnlockAppId))
523     return;
524   extensions::ExtensionSystem* extension_system =
525       extensions::ExtensionSystem::Get(profile_);
526   extension_system->extension_service()->ReloadExtension(
527       extension_misc::kEasyUnlockAppId);
528   NotifyUserUpdated();
529 }
530
531 void EasyUnlockService::UpdateAppState() {
532   if (IsAllowed()) {
533     LoadApp();
534
535 #if defined(OS_CHROMEOS)
536     if (!power_monitor_)
537       power_monitor_.reset(new PowerMonitor(this));
538 #endif
539   } else {
540     bool bluetooth_waking_up = false;
541 #if defined(OS_CHROMEOS)
542     // If the service is not allowed due to bluetooth not being detected just
543     // after system suspend is done, give bluetooth more time to be detected
544     // before disabling the app (and resetting screenlock state).
545     bluetooth_waking_up =
546         power_monitor_.get() && power_monitor_->waking_up() &&
547         !bluetooth_detector_->IsPresent();
548 #endif
549
550     if (!bluetooth_waking_up) {
551       DisableAppIfLoaded();
552       ResetScreenlockState();
553 #if defined(OS_CHROMEOS)
554       power_monitor_.reset();
555 #endif
556     }
557   }
558 }
559
560 void EasyUnlockService::NotifyUserUpdated() {
561   std::string user_id = GetUserEmail();
562   if (user_id.empty())
563     return;
564
565   // Notify the easy unlock app that the user info changed.
566   extensions::api::easy_unlock_private::UserInfo info;
567   info.user_id = user_id;
568   info.logged_in = GetType() == TYPE_REGULAR;
569   info.data_ready = info.logged_in || GetRemoteDevices() != NULL;
570
571   scoped_ptr<base::ListValue> args(new base::ListValue());
572   args->Append(info.ToValue().release());
573
574   scoped_ptr<extensions::Event> event(new extensions::Event(
575       extensions::api::easy_unlock_private::OnUserInfoUpdated::kEventName,
576       args.Pass()));
577
578   extensions::EventRouter::Get(profile_)->DispatchEventToExtension(
579        extension_misc::kEasyUnlockAppId, event.Pass());
580 }
581
582 void EasyUnlockService::NotifyTurnOffOperationStatusChanged() {
583   FOR_EACH_OBSERVER(
584       EasyUnlockServiceObserver, observers_, OnTurnOffOperationStatusChanged());
585 }
586
587 void EasyUnlockService::ResetScreenlockState() {
588   screenlock_state_handler_.reset();
589   auth_attempt_.reset();
590 }
591
592 void EasyUnlockService::SetScreenlockHardlockedState(
593     EasyUnlockScreenlockStateHandler::HardlockState state) {
594   if (screenlock_state_handler_)
595     screenlock_state_handler_->SetHardlockState(state);
596   if (state != EasyUnlockScreenlockStateHandler::NO_HARDLOCK)
597     auth_attempt_.reset();
598 }
599
600 void EasyUnlockService::Initialize() {
601   InitializeInternal();
602
603 #if defined(OS_CHROMEOS)
604   // Only start Bluetooth detection for ChromeOS since the feature is
605   // only offered on ChromeOS. Enabling this on non-ChromeOS platforms
606   // previously introduced a performance regression: http://crbug.com/404482
607   // Make sure not to reintroduce a performance regression if re-enabling on
608   // additional platforms.
609   // TODO(xiyuan): Revisit when non-chromeos platforms are supported.
610   bluetooth_detector_->Initialize();
611 #endif  // defined(OS_CHROMEOS)
612 }
613
614 void EasyUnlockService::OnBluetoothAdapterPresentChanged() {
615   UpdateAppState();
616 }
617
618 void EasyUnlockService::SetHardlockStateForUser(
619       const std::string& user_id,
620       EasyUnlockScreenlockStateHandler::HardlockState state) {
621   DCHECK(!user_id.empty());
622
623   PrefService* local_state = GetLocalState();
624   if (!local_state)
625     return;
626
627   DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
628   update->SetIntegerWithoutPathExpansion(user_id, static_cast<int>(state));
629
630   if (GetUserEmail() == user_id)
631     SetScreenlockHardlockedState(state);
632 }
633
634 #if defined(OS_CHROMEOS)
635 void EasyUnlockService::OnCryptohomeKeysFetchedForChecking(
636     const std::string& user_id,
637     const std::set<std::string> paired_devices,
638     bool success,
639     const chromeos::EasyUnlockDeviceKeyDataList& key_data_list) {
640   DCHECK(!user_id.empty() && !paired_devices.empty());
641
642   if (!success) {
643     SetHardlockStateForUser(user_id,
644                             EasyUnlockScreenlockStateHandler::NO_PAIRING);
645     return;
646   }
647
648   std::set<std::string> devices_in_cryptohome;
649   for (const auto& device_key_data : key_data_list)
650     devices_in_cryptohome.insert(device_key_data.psk);
651
652   if (paired_devices != devices_in_cryptohome ||
653       GetHardlockState() == EasyUnlockScreenlockStateHandler::NO_PAIRING) {
654     SetHardlockStateForUser(
655         user_id,
656         devices_in_cryptohome.empty()
657             ? EasyUnlockScreenlockStateHandler::PAIRING_ADDED
658             : EasyUnlockScreenlockStateHandler::PAIRING_CHANGED);
659   }
660 }
661 #endif
662
663 void EasyUnlockService::PrepareForSuspend() {
664   DisableAppIfLoaded();
665   if (screenlock_state_handler_ && screenlock_state_handler_->IsActive()) {
666     UpdateScreenlockState(
667         EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING);
668   }
669 }
670