Home | History | Annotate | Download | only in easy_unlock
      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 "base/bind.h"
      6 #include "base/message_loop/message_loop.h"
      7 #include "chrome/browser/chrome_notification_types.h"
      8 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_reauth.h"
      9 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
     10 #include "chrome/browser/signin/screenlock_bridge.h"
     11 #include "chrome/grit/generated_resources.h"
     12 #include "chromeos/dbus/dbus_thread_manager.h"
     13 #include "chromeos/dbus/session_manager_client.h"
     14 #include "chromeos/login/auth/auth_status_consumer.h"
     15 #include "chromeos/login/auth/user_context.h"
     16 #include "content/public/browser/notification_details.h"
     17 #include "content/public/browser/notification_observer.h"
     18 #include "content/public/browser/notification_registrar.h"
     19 #include "content/public/browser/notification_service.h"
     20 #include "ui/base/l10n/l10n_util.h"
     21 
     22 namespace chromeos {
     23 
     24 namespace {
     25 
     26 void EndReauthAttempt();
     27 
     28 // Performs the actual reauth flow and returns the user context it obtains.
     29 class ReauthHandler : public content::NotificationObserver,
     30                       public chromeos::AuthStatusConsumer {
     31  public:
     32   explicit ReauthHandler(EasyUnlockReauth::UserContextCallback callback)
     33       : callback_(callback) {}
     34 
     35   virtual ~ReauthHandler() {}
     36 
     37   bool Start() {
     38     ScreenLocker* screen_locker = ScreenLocker::default_screen_locker();
     39     if (screen_locker && screen_locker->locked()) {
     40       NOTREACHED();
     41       return false;
     42     }
     43 
     44     user_manager::UserManager* user_manager = user_manager::UserManager::Get();
     45     if (user_manager->GetPrimaryUser() != user_manager->GetActiveUser() ||
     46         user_manager->GetUnlockUsers().size() != 1) {
     47       LOG(WARNING) << "Only primary users in non-multiprofile sessions are "
     48                    << "currently supported for reauth.";
     49       return false;
     50     }
     51 
     52     notification_registrar_.Add(this,
     53                                 chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
     54                                 content::NotificationService::AllSources());
     55 
     56     SessionManagerClient* session_manager =
     57         chromeos::DBusThreadManager::Get()->GetSessionManagerClient();
     58     session_manager->RequestLockScreen();
     59     return true;
     60   }
     61 
     62   // content::NotificationObserver
     63   virtual void Observe(int type,
     64                        const content::NotificationSource& source,
     65                        const content::NotificationDetails& details) override {
     66     CHECK(type == chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED);
     67     bool is_screen_locked = *content::Details<bool>(details).ptr();
     68     DCHECK(is_screen_locked);
     69     notification_registrar_.RemoveAll();
     70 
     71     // TODO(tengs): Add an explicit reauth state to the locker and account
     72     // picker, so we can customize the UI.
     73     ScreenLocker* screen_locker = ScreenLocker::default_screen_locker();
     74     screen_locker->SetLoginStatusConsumer(this);
     75 
     76     // Show tooltip explaining reauth.
     77     ScreenlockBridge::UserPodCustomIconOptions icon_options;
     78     icon_options.SetIcon(ScreenlockBridge::USER_POD_CUSTOM_ICON_NONE);
     79     icon_options.SetTooltip(
     80         l10n_util::GetStringUTF16(
     81             IDS_SMART_LOCK_SCREENLOCK_TOOLTIP_HARDLOCK_REAUTH_USER),
     82         true);
     83 
     84     const user_manager::UserList& lock_users = screen_locker->users();
     85     DCHECK(lock_users.size() == 1);
     86     ScreenlockBridge::Get()->lock_handler()->ShowUserPodCustomIcon(
     87         lock_users[0]->email(), icon_options);
     88   }
     89 
     90   // chromeos::AuthStatusConsumer:
     91   virtual void OnAuthSuccess(
     92       const chromeos::UserContext& user_context) override {
     93     callback_.Run(user_context);
     94     // Schedule deletion.
     95     base::MessageLoopForUI::current()->PostTask(FROM_HERE,
     96                                                 base::Bind(&EndReauthAttempt));
     97   }
     98 
     99   virtual void OnAuthFailure(const chromeos::AuthFailure& error) override {}
    100 
    101  private:
    102   content::NotificationRegistrar notification_registrar_;
    103   EasyUnlockReauth::UserContextCallback callback_;
    104 
    105   DISALLOW_COPY_AND_ASSIGN(ReauthHandler);
    106 };
    107 
    108 ReauthHandler* g_reauth_handler = NULL;
    109 
    110 void EndReauthAttempt() {
    111   DCHECK(base::MessageLoopForUI::IsCurrent());
    112   DCHECK(g_reauth_handler);
    113   delete g_reauth_handler;
    114   g_reauth_handler = NULL;
    115 }
    116 
    117 }  // namespace
    118 
    119 // static.
    120 bool EasyUnlockReauth::ReauthForUserContext(
    121     base::Callback<void(const UserContext&)> callback) {
    122   DCHECK(base::MessageLoopForUI::IsCurrent());
    123   if (g_reauth_handler)
    124     return false;
    125 
    126   g_reauth_handler = new ReauthHandler(callback);
    127   return g_reauth_handler->Start();
    128 }
    129 
    130 }  // namespace chromeos
    131