Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/login/login_performer.h" | 5 #include "chrome/browser/chromeos/login/login_performer.h" |
| 6 | 6 |
| 7 #include <string> | |
| 8 | |
| 9 #include "app/l10n_util.h" | |
| 10 #include "app/resource_bundle.h" | |
| 7 #include "base/logging.h" | 11 #include "base/logging.h" |
| 8 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 9 #include "chrome/browser/browser_process.h" | 13 #include "chrome/browser/browser_process.h" |
| 10 #include "chrome/browser/browser_thread.h" | 14 #include "chrome/browser/browser_thread.h" |
| 11 #include "chrome/browser/chromeos/boot_times_loader.h" | 15 #include "chrome/browser/chromeos/boot_times_loader.h" |
| 16 #include "chrome/browser/chromeos/cros/cros_library.h" | |
| 17 #include "chrome/browser/chromeos/cros/screen_lock_library.h" | |
| 12 #include "chrome/browser/chromeos/login/login_utils.h" | 18 #include "chrome/browser/chromeos/login/login_utils.h" |
| 19 #include "chrome/browser/chromeos/login/screen_locker.h" | |
| 13 #include "chrome/browser/chromeos/user_cros_settings_provider.h" | 20 #include "chrome/browser/chromeos/user_cros_settings_provider.h" |
| 21 #include "chrome/common/notification_service.h" | |
| 22 #include "chrome/common/notification_type.h" | |
| 14 #include "chrome/browser/profile.h" | 23 #include "chrome/browser/profile.h" |
| 15 #include "chrome/browser/profile_manager.h" | 24 #include "chrome/browser/profile_manager.h" |
| 25 #include "grit/generated_resources.h" | |
| 16 | 26 |
| 17 namespace chromeos { | 27 namespace chromeos { |
| 18 | 28 |
| 19 namespace { | 29 // Initialize default LoginPerformer. |
| 20 } // namespace | 30 // static |
| 31 LoginPerformer* LoginPerformer::default_performer_ = NULL; | |
| 21 | 32 |
| 22 LoginPerformer::LoginPerformer(Delegate* delegate) | 33 LoginPerformer::LoginPerformer(Delegate* delegate) |
| 23 : last_login_failure_(LoginFailure::None()), | 34 : last_login_failure_(LoginFailure::None()), |
| 24 delegate_(delegate) {} | 35 delegate_(delegate), |
| 36 password_changed_(false) { | |
| 37 DCHECK(default_performer_ == NULL); | |
|
whywhat
2010/11/25 15:40:37
Add a message to DCHECK?
Nikita (slow)
2010/11/29 11:20:25
Done. Plus added message for bunch of other DCHECK
| |
| 38 default_performer_ = this; | |
| 39 } | |
| 40 | |
| 41 LoginPerformer::~LoginPerformer() { | |
| 42 DVLOG(1) << "Deleting LoginPerformer"; | |
|
whywhat
2010/11/25 15:40:37
DCHECK for default_performer_ not NULL?
Nikita (slow)
2010/11/29 11:20:25
Done.
| |
| 43 default_performer_ = NULL; | |
| 44 } | |
| 25 | 45 |
| 26 //////////////////////////////////////////////////////////////////////////////// | 46 //////////////////////////////////////////////////////////////////////////////// |
| 27 // LoginPerformer, LoginStatusConsumer implementation: | 47 // LoginPerformer, LoginStatusConsumer implementation: |
| 28 | 48 |
| 29 void LoginPerformer::OnLoginFailure(const LoginFailure& failure) { | 49 void LoginPerformer::OnLoginFailure(const LoginFailure& failure) { |
| 30 last_login_failure_ = failure; | 50 DVLOG(1) << "failure.reason " << failure.reason(); |
| 31 if (delegate_) { | 51 DVLOG(1) << "failure.error.state " << failure.error().state(); |
| 32 captcha_.clear(); | 52 |
| 33 captcha_token_.clear(); | 53 last_login_failure_ = failure; |
| 34 if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED && | 54 if (delegate_) { |
| 35 failure.error().state() == GoogleServiceAuthError::CAPTCHA_REQUIRED) { | 55 captcha_.clear(); |
| 36 captcha_token_ = failure.error().captcha().token; | 56 captcha_token_.clear(); |
| 37 } | 57 if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED && |
| 38 delegate_->OnLoginFailure(failure); | 58 failure.error().state() == GoogleServiceAuthError::CAPTCHA_REQUIRED) { |
| 39 } else { | 59 captcha_token_ = failure.error().captcha().token; |
| 40 // TODO(nkostylev): Provide blocking UI using ScreenLocker. | 60 } |
| 41 } | 61 delegate_->OnLoginFailure(failure); |
| 62 return; | |
| 63 } | |
| 64 | |
| 65 // Consequent online login failure with blocking UI on. | |
| 66 // No difference between cases whether screen was locked by the user or | |
| 67 // by LoginPerformer. | |
| 68 // Display recoverable error message using ScreenLocker, | |
| 69 // force sign out otherwise. | |
| 70 if (ScreenLocker::default_screen_locker()) { | |
| 71 ResolveLockLoginFailure(); | |
| 72 return; | |
| 73 } | |
| 74 | |
| 75 // Offline auth - OK, online auth - failed. | |
| 76 if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED) { | |
| 77 ResolveInitialNetworkAuthFailure(); | |
| 78 } else if (failure.reason() == LoginFailure::LOGIN_TIMED_OUT) { | |
| 79 LOG(INFO) << "Online login timed out. " | |
| 80 << "Granting user access based on offline auth only."; | |
| 81 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
| 82 } else { | |
| 83 // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS: | |
| 84 // happens during offline auth only. | |
| 85 // UNLOCK_FAILED is used during normal screen lock case. | |
| 86 // TODO(nkostylev) DATA_REMOVAL_FAILED - ? | |
| 87 NOTREACHED(); | |
| 88 } | |
| 42 } | 89 } |
| 43 | 90 |
| 44 void LoginPerformer::OnLoginSuccess( | 91 void LoginPerformer::OnLoginSuccess( |
| 45 const std::string& username, | 92 const std::string& username, |
| 46 const std::string& password, | 93 const std::string& password, |
| 47 const GaiaAuthConsumer::ClientLoginResult& credentials, | 94 const GaiaAuthConsumer::ClientLoginResult& credentials, |
| 48 bool pending_requests) { | 95 bool pending_requests) { |
| 96 VLOG(1) << "LoginSuccess, pending_requests " << pending_requests; | |
| 49 if (delegate_) { | 97 if (delegate_) { |
| 50 delegate_->OnLoginSuccess(username, | 98 delegate_->OnLoginSuccess(username, |
| 51 password, | 99 password, |
| 52 credentials, | 100 credentials, |
| 53 pending_requests); | 101 pending_requests); |
| 54 if (!pending_requests) | 102 if (!pending_requests) |
| 55 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 103 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 56 } else { | 104 } else { |
| 57 DCHECK(!pending_requests); | 105 //DCHECK(!pending_requests); |
| 58 // Online login has succeeded. Delete our instance. | 106 // Online login has succeeded. |
| 107 // TODO(nkostylev): Execute CookieFetcher->AttemptFetch() here once | |
| 108 // async login is implemented - waiting for CL merge. | |
| 109 if (ScreenLocker::default_screen_locker()) { | |
| 110 DVLOG(1) << "Online login OK - unlocking screen."; | |
| 111 RequestScreenUnlock(); | |
| 112 return; | |
| 113 } | |
| 59 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 114 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
| 60 } | 115 } |
| 61 } | 116 } |
| 62 | 117 |
| 63 void LoginPerformer::OnOffTheRecordLoginSuccess() { | 118 void LoginPerformer::OnOffTheRecordLoginSuccess() { |
| 64 if (delegate_) | 119 if (delegate_) |
| 65 delegate_->OnOffTheRecordLoginSuccess(); | 120 delegate_->OnOffTheRecordLoginSuccess(); |
| 66 else | 121 else |
| 67 NOTREACHED(); | 122 NOTREACHED(); |
| 68 } | 123 } |
| 69 | 124 |
| 70 void LoginPerformer::OnPasswordChangeDetected( | 125 void LoginPerformer::OnPasswordChangeDetected( |
| 71 const GaiaAuthConsumer::ClientLoginResult& credentials) { | 126 const GaiaAuthConsumer::ClientLoginResult& credentials) { |
| 72 cached_credentials_ = credentials; | 127 cached_credentials_ = credentials; |
| 73 if (delegate_) { | 128 if (delegate_) { |
| 74 delegate_->OnPasswordChangeDetected(credentials); | 129 delegate_->OnPasswordChangeDetected(credentials); |
| 75 } else { | 130 } else { |
| 76 // TODO(nkostylev): Provide blocking UI using ScreenLocker. | 131 last_login_failure_ = |
| 132 LoginFailure::FromNetworkAuthFailure(GoogleServiceAuthError( | |
| 133 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS)); | |
| 134 password_changed_ = true; | |
| 135 DVLOG(1) << "Password change detected - locking screen."; | |
| 136 RequestScreenLock(); | |
| 77 } | 137 } |
| 78 } | 138 } |
| 79 | 139 |
| 80 //////////////////////////////////////////////////////////////////////////////// | 140 //////////////////////////////////////////////////////////////////////////////// |
| 81 // LoginPerformer, SignedSettingsHelper::Callback implementation: | 141 // LoginPerformer, SignedSettingsHelper::Callback implementation: |
| 82 | 142 |
| 83 void LoginPerformer::OnCheckWhiteListCompleted(bool success, | 143 void LoginPerformer::OnCheckWhiteListCompleted(bool success, |
| 84 const std::string& email) { | 144 const std::string& email) { |
| 85 if (success) { | 145 if (success) { |
| 86 // Whitelist check passed, continue with authentication. | 146 // Whitelist check passed, continue with authentication. |
| 87 StartAuthentication(); | 147 StartAuthentication(); |
| 88 } else { | 148 } else { |
| 89 if (delegate_) | 149 if (delegate_) |
| 90 delegate_->WhiteListCheckFailed(email); | 150 delegate_->WhiteListCheckFailed(email); |
| 91 else | 151 else |
| 92 NOTREACHED(); | 152 NOTREACHED(); |
| 93 } | 153 } |
| 94 } | 154 } |
| 95 | 155 |
| 96 //////////////////////////////////////////////////////////////////////////////// | 156 //////////////////////////////////////////////////////////////////////////////// |
| 157 // LoginPerformer, NotificationObserver implementation: | |
| 158 // | |
| 159 | |
| 160 void LoginPerformer::Observe(NotificationType type, | |
| 161 const NotificationSource& source, | |
| 162 const NotificationDetails& details) { | |
| 163 if (type != NotificationType::SCREEN_LOCK_STATE_CHANGED) | |
| 164 return; | |
| 165 | |
| 166 bool is_screen_locked = *Details<bool>(details).ptr(); | |
| 167 if (is_screen_locked) | |
| 168 ResolveScreenLocked(); | |
| 169 else | |
| 170 ResolveScreenUnlocked(); | |
| 171 } | |
| 172 | |
| 173 //////////////////////////////////////////////////////////////////////////////// | |
| 97 // LoginPerformer, public: | 174 // LoginPerformer, public: |
| 98 | 175 |
| 99 void LoginPerformer::Login(const std::string& username, | 176 void LoginPerformer::Login(const std::string& username, |
| 100 const std::string& password) { | 177 const std::string& password) { |
| 101 username_ = username; | 178 username_ = username; |
| 102 password_ = password; | 179 password_ = password; |
| 103 if (UserCrosSettingsProvider::cached_allow_new_user()) { | 180 // Whitelist is performed during offline login only. |
| 181 if (ScreenLocker::default_screen_locker() || | |
| 182 UserCrosSettingsProvider::cached_allow_new_user()) { | |
| 104 // Starts authentication if guest login is allowed. | 183 // Starts authentication if guest login is allowed. |
| 105 StartAuthentication(); | 184 StartAuthentication(); |
| 106 } else { | 185 } else { |
| 107 // Otherwise, do whitelist check first. | 186 // Otherwise, do whitelist check first. |
| 108 SignedSettingsHelper::Get()->StartCheckWhitelistOp( | 187 SignedSettingsHelper::Get()->StartCheckWhitelistOp( |
| 109 username, this); | 188 username, this); |
| 110 } | 189 } |
| 111 } | 190 } |
| 112 | 191 |
| 113 void LoginPerformer::LoginOffTheRecord() { | 192 void LoginPerformer::LoginOffTheRecord() { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 133 BrowserThread::UI, FROM_HERE, | 212 BrowserThread::UI, FROM_HERE, |
| 134 NewRunnableMethod(authenticator_.get(), | 213 NewRunnableMethod(authenticator_.get(), |
| 135 &Authenticator::ResyncEncryptedData, | 214 &Authenticator::ResyncEncryptedData, |
| 136 cached_credentials_)); | 215 cached_credentials_)); |
| 137 cached_credentials_ = GaiaAuthConsumer::ClientLoginResult(); | 216 cached_credentials_ = GaiaAuthConsumer::ClientLoginResult(); |
| 138 } | 217 } |
| 139 | 218 |
| 140 //////////////////////////////////////////////////////////////////////////////// | 219 //////////////////////////////////////////////////////////////////////////////// |
| 141 // LoginPerformer, private: | 220 // LoginPerformer, private: |
| 142 | 221 |
| 222 void LoginPerformer::RequestScreenLock() { | |
| 223 DVLOG(1) << "Screen lock requested"; | |
| 224 if (ScreenLocker::default_screen_locker()) { | |
| 225 DVLOG(1) << "Screen already locked"; | |
| 226 ResolveScreenLocked(); | |
| 227 } else { | |
| 228 registrar_.Add( | |
| 229 this, | |
| 230 NotificationType::SCREEN_LOCK_STATE_CHANGED, | |
| 231 NotificationService::AllSources()); | |
| 232 chromeos::CrosLibrary::Get()->GetScreenLockLibrary()-> | |
| 233 NotifyScreenLockRequested(); | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 void LoginPerformer::RequestScreenUnlock() { | |
| 238 DVLOG(1) << "Screen unlock requested"; | |
| 239 if (ScreenLocker::default_screen_locker()) { | |
| 240 chromeos::CrosLibrary::Get()->GetScreenLockLibrary()-> | |
| 241 NotifyScreenUnlockRequested(); | |
| 242 // Will unsubscribe from notifications once unlock is successful. | |
| 243 } else { | |
| 244 LOG(ERROR) << "Screen is not locked"; | |
| 245 NOTREACHED(); | |
| 246 } | |
| 247 } | |
| 248 | |
| 249 void LoginPerformer::ResolveInitialNetworkAuthFailure() { | |
| 250 DVLOG(1) << "auth_error: " << last_login_failure_.error().state(); | |
| 251 | |
| 252 switch (last_login_failure_.error().state()) { | |
| 253 case GoogleServiceAuthError::CONNECTION_FAILED: | |
| 254 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: | |
| 255 case GoogleServiceAuthError::TWO_FACTOR: | |
| 256 case GoogleServiceAuthError::REQUEST_CANCELED: | |
| 257 // Offline auth already done. Online auth will be done next time | |
| 258 // or once user accesses web property. | |
| 259 LOG(INFO) << "Granting user access based on offline auth only. " | |
| 260 << "Online login failed with " | |
| 261 << last_login_failure_.error().state(); | |
| 262 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
| 263 return; | |
| 264 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: | |
| 265 // Offline auth OK, so it might be the case of changed password. | |
| 266 password_changed_ = true; | |
| 267 case GoogleServiceAuthError::USER_NOT_SIGNED_UP: | |
| 268 case GoogleServiceAuthError::ACCOUNT_DELETED: | |
| 269 case GoogleServiceAuthError::ACCOUNT_DISABLED: | |
| 270 // Access not granted. User has to sign out. | |
| 271 // Request screen lock & show error message there. | |
| 272 case GoogleServiceAuthError::CAPTCHA_REQUIRED: | |
| 273 // User is requested to enter CAPTCHA challenge. | |
| 274 RequestScreenLock(); | |
| 275 return; | |
| 276 default: | |
| 277 // Unless there's new GoogleServiceAuthErrors state has been added. | |
| 278 NOTREACHED(); | |
| 279 return; | |
| 280 } | |
| 281 } | |
| 282 | |
| 283 void LoginPerformer::ResolveLockLoginFailure() { | |
| 284 if (last_login_failure_.reason() == LoginFailure::LOGIN_TIMED_OUT) { | |
| 285 LOG(INFO) << "Online login timed out - unlocking screen. " | |
| 286 << "Granting user access based on offline auth only."; | |
| 287 RequestScreenUnlock(); | |
| 288 return; | |
| 289 } else if (last_login_failure_.reason() == | |
| 290 LoginFailure::NETWORK_AUTH_FAILED) { | |
| 291 ResolveLockNetworkAuthFailure(); | |
| 292 return; | |
| 293 } else if (last_login_failure_.reason() == | |
| 294 LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME || | |
| 295 last_login_failure_.reason() == | |
| 296 LoginFailure::DATA_REMOVAL_FAILED) { | |
| 297 LOG(ERROR) << "Cryptohome error, forcing sign out."; | |
| 298 } else { | |
| 299 // COULD_NOT_MOUNT_TMPFS, UNLOCK_FAILED should not happen here. | |
| 300 NOTREACHED(); | |
| 301 } | |
| 302 ScreenLocker::default_screen_locker()->Signout(); | |
| 303 } | |
| 304 | |
| 305 void LoginPerformer::ResolveLockNetworkAuthFailure() { | |
| 306 DCHECK(ScreenLocker::default_screen_locker()); | |
| 307 DCHECK(last_login_failure_.reason() == LoginFailure::NETWORK_AUTH_FAILED); | |
| 308 | |
| 309 std::wstring msg; | |
| 310 bool sign_out_only = false; | |
| 311 | |
| 312 DVLOG(1) << "auth_error: " << last_login_failure_.error().state(); | |
| 313 | |
| 314 switch (last_login_failure_.error().state()) { | |
| 315 case GoogleServiceAuthError::CONNECTION_FAILED: | |
| 316 case GoogleServiceAuthError::SERVICE_UNAVAILABLE: | |
| 317 case GoogleServiceAuthError::TWO_FACTOR: | |
| 318 case GoogleServiceAuthError::REQUEST_CANCELED: | |
| 319 // Offline auth already done. Online auth will be done next time | |
| 320 // or once user accesses web property. | |
| 321 LOG(INFO) << "Granting user access based on offline auth only. " | |
| 322 << "Online login failed with " | |
| 323 << last_login_failure_.error().state(); | |
| 324 RequestScreenUnlock(); | |
| 325 return; | |
| 326 case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: | |
| 327 // Password change detected. | |
| 328 msg = l10n_util::GetString(IDS_LOGIN_ERROR_PASSWORD_CHANGED); | |
| 329 break; | |
| 330 case GoogleServiceAuthError::USER_NOT_SIGNED_UP: | |
| 331 case GoogleServiceAuthError::ACCOUNT_DELETED: | |
| 332 case GoogleServiceAuthError::ACCOUNT_DISABLED: | |
| 333 // Access not granted. User has to sign out. | |
| 334 // Show error message using existing screen lock. | |
| 335 msg = l10n_util::GetString(IDS_LOGIN_ERROR_RESTRICTED); | |
| 336 sign_out_only = true; | |
| 337 break; | |
| 338 case GoogleServiceAuthError::CAPTCHA_REQUIRED: | |
| 339 // User is requested to enter CAPTCHA challenge. | |
| 340 msg = l10n_util::GetString(IDS_LOGIN_ERROR_AUTHENTICATING); | |
| 341 // TODO(nkostylev): Instruct ScreenLocker to show CAPTCHA input. | |
| 342 break; | |
| 343 default: | |
| 344 // Unless there's new GoogleServiceAuthError state has been added. | |
| 345 NOTREACHED(); | |
| 346 break; | |
| 347 } | |
| 348 | |
| 349 ScreenLocker::default_screen_locker()->ShowErrorMessage(msg, sign_out_only); | |
| 350 } | |
| 351 | |
| 352 void LoginPerformer::ResolveScreenLocked() { | |
| 353 DVLOG(1) << "Screen locked"; | |
| 354 ResolveLockNetworkAuthFailure(); | |
| 355 } | |
| 356 | |
| 357 void LoginPerformer::ResolveScreenUnlocked() { | |
| 358 DVLOG(1) << "Screen unlocked"; | |
| 359 registrar_.RemoveAll(); | |
| 360 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | |
| 361 } | |
| 362 | |
| 143 void LoginPerformer::StartAuthentication() { | 363 void LoginPerformer::StartAuthentication() { |
| 364 DVLOG(1) << "Auth started"; | |
| 144 BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false); | 365 BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false); |
| 145 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); | |
| 146 Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile(); | 366 Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile(); |
| 147 BrowserThread::PostTask( | 367 if (delegate_) { |
| 148 BrowserThread::UI, FROM_HERE, | 368 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); |
| 149 NewRunnableMethod(authenticator_.get(), | 369 BrowserThread::PostTask( |
| 150 &Authenticator::AuthenticateToLogin, | 370 BrowserThread::UI, FROM_HERE, |
| 151 profile, | 371 NewRunnableMethod(authenticator_.get(), |
| 152 username_, | 372 &Authenticator::AuthenticateToLogin, |
| 153 password_, | 373 profile, |
| 154 captcha_token_, | 374 username_, |
| 155 captcha_)); | 375 password_, |
| 376 captcha_token_, | |
| 377 captcha_)); | |
| 378 } else { | |
| 379 DCHECK(authenticator_.get()); | |
| 380 // At this point offline auth has been successful, | |
| 381 // retry online auth, using existing Authenticator instance. | |
| 382 BrowserThread::PostTask( | |
| 383 BrowserThread::UI, FROM_HERE, | |
| 384 NewRunnableMethod(authenticator_.get(), | |
| 385 &Authenticator::RetryAuth, | |
| 386 profile, | |
| 387 username_, | |
| 388 password_, | |
| 389 captcha_token_, | |
| 390 captcha_)); | |
| 391 } | |
| 156 password_.clear(); | 392 password_.clear(); |
| 157 } | 393 } |
| 158 | 394 |
| 159 } // namespace chromeos | 395 } // namespace chromeos |
| OLD | NEW |