Home | History | Annotate | Download | only in login
      1 // Copyright (c) 2012 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/chromeos/login/login_performer.h"
      6 
      7 #include <string>
      8 
      9 #include "base/bind.h"
     10 #include "base/logging.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/metrics/histogram.h"
     13 #include "base/prefs/pref_service.h"
     14 #include "base/strings/utf_string_conversions.h"
     15 #include "base/threading/thread_restrictions.h"
     16 #include "chrome/browser/browser_process.h"
     17 #include "chrome/browser/chrome_notification_types.h"
     18 #include "chrome/browser/chromeos/boot_times_loader.h"
     19 #include "chrome/browser/chromeos/login/login_utils.h"
     20 #include "chrome/browser/chromeos/login/managed/locally_managed_user_login_flow.h"
     21 #include "chrome/browser/chromeos/login/user_manager.h"
     22 #include "chrome/browser/chromeos/policy/device_local_account_policy_service.h"
     23 #include "chrome/browser/chromeos/profiles/profile_helper.h"
     24 #include "chrome/browser/chromeos/settings/cros_settings.h"
     25 #include "chrome/browser/chromeos/settings/cros_settings_names.h"
     26 #include "chrome/browser/policy/browser_policy_connector.h"
     27 #include "chrome/common/pref_names.h"
     28 #include "chromeos/dbus/dbus_thread_manager.h"
     29 #include "chromeos/dbus/session_manager_client.h"
     30 #include "content/public/browser/browser_thread.h"
     31 #include "content/public/browser/notification_service.h"
     32 #include "content/public/browser/notification_types.h"
     33 #include "content/public/browser/user_metrics.h"
     34 #include "google_apis/gaia/gaia_auth_util.h"
     35 #include "grit/generated_resources.h"
     36 #include "net/cookies/cookie_monster.h"
     37 #include "net/cookies/cookie_store.h"
     38 #include "net/url_request/url_request_context.h"
     39 #include "net/url_request/url_request_context_getter.h"
     40 #include "ui/base/l10n/l10n_util.h"
     41 #include "ui/base/resource/resource_bundle.h"
     42 
     43 using content::BrowserThread;
     44 using content::UserMetricsAction;
     45 
     46 namespace chromeos {
     47 
     48 LoginPerformer::LoginPerformer(Delegate* delegate)
     49     : online_attempt_host_(this),
     50       last_login_failure_(LoginFailure::LoginFailureNone()),
     51       delegate_(delegate),
     52       password_changed_(false),
     53       password_changed_callback_count_(0),
     54       auth_mode_(AUTH_MODE_INTERNAL),
     55       weak_factory_(this) {
     56 }
     57 
     58 LoginPerformer::~LoginPerformer() {
     59   DVLOG(1) << "Deleting LoginPerformer";
     60   if (authenticator_.get())
     61     authenticator_->SetConsumer(NULL);
     62 }
     63 
     64 ////////////////////////////////////////////////////////////////////////////////
     65 // LoginPerformer, LoginStatusConsumer implementation:
     66 
     67 void LoginPerformer::OnLoginFailure(const LoginFailure& failure) {
     68   content::RecordAction(UserMetricsAction("Login_Failure"));
     69   UMA_HISTOGRAM_ENUMERATION("Login.FailureReason", failure.reason(),
     70                             LoginFailure::NUM_FAILURE_REASONS);
     71 
     72   DVLOG(1) << "failure.reason " << failure.reason();
     73   DVLOG(1) << "failure.error.state " << failure.error().state();
     74 
     75   last_login_failure_ = failure;
     76   if (delegate_) {
     77     delegate_->OnLoginFailure(failure);
     78     return;
     79   } else {
     80     // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS:
     81     // happens during offline auth only.
     82     NOTREACHED();
     83   }
     84 }
     85 
     86 void LoginPerformer::OnRetailModeLoginSuccess(
     87     const UserContext& user_context) {
     88   content::RecordAction(
     89       UserMetricsAction("Login_DemoUserLoginSuccess"));
     90   LoginStatusConsumer::OnRetailModeLoginSuccess(user_context);
     91 }
     92 
     93 void LoginPerformer::OnLoginSuccess(
     94     const UserContext& user_context,
     95     bool pending_requests,
     96     bool using_oauth) {
     97   content::RecordAction(UserMetricsAction("Login_Success"));
     98   // The value of |pending_requests| indicates:
     99   // 0 - New regular user, login success offline and online.
    100   //     - or -
    101   //     Existing regular user, login success offline and online, offline
    102   //     authentication took longer than online authentication.
    103   //     - or -
    104   //     Public account user, login successful.
    105   // 1 - Existing regular user, login success offline only.
    106   UMA_HISTOGRAM_ENUMERATION("Login.SuccessReason", pending_requests, 2);
    107 
    108   VLOG(1) << "LoginSuccess hash: " << user_context.username_hash
    109           << ", pending_requests " << pending_requests;
    110   DCHECK(delegate_);
    111   // After delegate_->OnLoginSuccess(...) is called, delegate_ releases
    112   // LoginPerformer ownership. LP now manages it's lifetime on its own.
    113   DCHECK(!pending_requests);
    114   base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
    115 
    116   delegate_->OnLoginSuccess(user_context,
    117                             pending_requests,
    118                             using_oauth);
    119 }
    120 
    121 void LoginPerformer::OnOffTheRecordLoginSuccess() {
    122   content::RecordAction(
    123       UserMetricsAction("Login_GuestLoginSuccess"));
    124 
    125   if (delegate_)
    126     delegate_->OnOffTheRecordLoginSuccess();
    127   else
    128     NOTREACHED();
    129 }
    130 
    131 void LoginPerformer::OnPasswordChangeDetected() {
    132   password_changed_ = true;
    133   password_changed_callback_count_++;
    134   if (delegate_) {
    135     delegate_->OnPasswordChangeDetected();
    136   } else {
    137     NOTREACHED();
    138   }
    139 }
    140 
    141 void LoginPerformer::OnChecked(const std::string& username, bool success) {
    142   if (!delegate_) {
    143     // Delegate is reset in case of successful offline login.
    144     // See ExistingUserConstoller::OnLoginSuccess().
    145     // Case when user has changed password and enters old password
    146     // does not block user from sign in yet.
    147     return;
    148   }
    149   delegate_->OnOnlineChecked(username, success);
    150 }
    151 
    152 ////////////////////////////////////////////////////////////////////////////////
    153 // LoginPerformer, public:
    154 
    155 void LoginPerformer::PerformLogin(const UserContext& user_context,
    156                                   AuthorizationMode auth_mode) {
    157   auth_mode_ = auth_mode;
    158   user_context_ = user_context;
    159 
    160   CrosSettings* cros_settings = CrosSettings::Get();
    161 
    162   // Whitelist check is always performed during initial login.
    163   CrosSettingsProvider::TrustedStatus status =
    164       cros_settings->PrepareTrustedValues(
    165           base::Bind(&LoginPerformer::PerformLogin,
    166                      weak_factory_.GetWeakPtr(),
    167                      user_context_, auth_mode));
    168   // Must not proceed without signature verification.
    169   if (status == CrosSettingsProvider::PERMANENTLY_UNTRUSTED) {
    170     if (delegate_)
    171       delegate_->PolicyLoadFailed();
    172     else
    173       NOTREACHED();
    174     return;
    175   } else if (status != CrosSettingsProvider::TRUSTED) {
    176     // Value of AllowNewUser setting is still not verified.
    177     // Another attempt will be invoked after verification completion.
    178     return;
    179   }
    180 
    181   bool is_whitelisted = LoginUtils::IsWhitelisted(
    182       gaia::CanonicalizeEmail(user_context.username));
    183   if (is_whitelisted) {
    184     switch (auth_mode_) {
    185       case AUTH_MODE_EXTENSION:
    186         StartLoginCompletion();
    187         break;
    188       case AUTH_MODE_INTERNAL:
    189         StartAuthentication();
    190         break;
    191     }
    192   } else {
    193     if (delegate_)
    194       delegate_->WhiteListCheckFailed(user_context.username);
    195     else
    196       NOTREACHED();
    197   }
    198 }
    199 
    200 void LoginPerformer::LoginAsLocallyManagedUser(
    201     const UserContext& user_context) {
    202   DCHECK_EQ(UserManager::kLocallyManagedUserDomain,
    203             gaia::ExtractDomainName(user_context.username));
    204   // TODO(nkostylev): Check that policy allows locally managed user login.
    205   UserFlow* new_flow = new LocallyManagedUserLoginFlow(user_context.username);
    206   new_flow->set_host(
    207       UserManager::Get()->GetUserFlow(user_context.username)->host());
    208   UserManager::Get()->SetUserFlow(user_context.username, new_flow);
    209 
    210   authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
    211   BrowserThread::PostTask(
    212       BrowserThread::UI, FROM_HERE,
    213       base::Bind(&Authenticator::LoginAsLocallyManagedUser,
    214                  authenticator_.get(),
    215                  user_context));
    216 }
    217 
    218 void LoginPerformer::LoginRetailMode() {
    219   authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
    220   BrowserThread::PostTask(
    221       BrowserThread::UI, FROM_HERE,
    222       base::Bind(&Authenticator::LoginRetailMode, authenticator_.get()));
    223 }
    224 
    225 void LoginPerformer::LoginOffTheRecord() {
    226   authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
    227   BrowserThread::PostTask(
    228       BrowserThread::UI, FROM_HERE,
    229       base::Bind(&Authenticator::LoginOffTheRecord, authenticator_.get()));
    230 }
    231 
    232 void LoginPerformer::LoginAsPublicAccount(const std::string& username) {
    233   // Login is not allowed if policy could not be loaded for the account.
    234   policy::DeviceLocalAccountPolicyService* policy_service =
    235       g_browser_process->browser_policy_connector()->
    236           GetDeviceLocalAccountPolicyService();
    237   if (!policy_service || !policy_service->IsPolicyAvailableForUser(username)) {
    238     DCHECK(delegate_);
    239     if (delegate_)
    240       delegate_->PolicyLoadFailed();
    241     return;
    242   }
    243 
    244   authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
    245   BrowserThread::PostTask(
    246       BrowserThread::UI, FROM_HERE,
    247       base::Bind(&Authenticator::LoginAsPublicAccount, authenticator_.get(),
    248                  username));
    249 }
    250 
    251 void LoginPerformer::RecoverEncryptedData(const std::string& old_password) {
    252   BrowserThread::PostTask(
    253       BrowserThread::UI, FROM_HERE,
    254       base::Bind(&Authenticator::RecoverEncryptedData, authenticator_.get(),
    255                  old_password));
    256 }
    257 
    258 void LoginPerformer::ResyncEncryptedData() {
    259   BrowserThread::PostTask(
    260       BrowserThread::UI, FROM_HERE,
    261       base::Bind(&Authenticator::ResyncEncryptedData, authenticator_.get()));
    262 }
    263 
    264 ////////////////////////////////////////////////////////////////////////////////
    265 // LoginPerformer, private:
    266 
    267 void LoginPerformer::StartLoginCompletion() {
    268   DVLOG(1) << "Login completion started";
    269   BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false);
    270   Profile* profile = ProfileHelper::GetSigninProfile();
    271 
    272   authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
    273   BrowserThread::PostTask(
    274       BrowserThread::UI, FROM_HERE,
    275       base::Bind(&Authenticator::CompleteLogin, authenticator_.get(),
    276                  profile,
    277                  user_context_));
    278 
    279   user_context_.password.clear();
    280   user_context_.auth_code.clear();
    281 }
    282 
    283 void LoginPerformer::StartAuthentication() {
    284   DVLOG(1) << "Auth started";
    285   BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false);
    286   Profile* profile = ProfileHelper::GetSigninProfile();
    287   if (delegate_) {
    288     authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
    289     BrowserThread::PostTask(
    290         BrowserThread::UI, FROM_HERE,
    291         base::Bind(&Authenticator::AuthenticateToLogin, authenticator_.get(),
    292                    profile,
    293                    user_context_));
    294     // Make unobtrusive online check. It helps to determine password change
    295     // state in the case when offline login fails.
    296     online_attempt_host_.Check(profile, user_context_);
    297   } else {
    298     NOTREACHED();
    299   }
    300   user_context_.password.clear();
    301   user_context_.auth_code.clear();
    302 }
    303 
    304 }  // namespace chromeos
    305