Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Unified Diff: chrome/browser/chromeos/login/login_performer.cc

Issue 3583013: [cros] Add blocking UI on offline: OK, online auth: fail case. (Closed) Base URL: http://src.chromium.org/git/chromium.git
Patch Set: check whether screen is already locked/unlocked Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/login/login_performer.cc
diff --git a/chrome/browser/chromeos/login/login_performer.cc b/chrome/browser/chromeos/login/login_performer.cc
index eb5304d2e41f9ae696f9c4729ef8cd027e95e1af..29ba6eac8c8320b8635503029da0406a8f16efc4 100644
--- a/chrome/browser/chromeos/login/login_performer.cc
+++ b/chrome/browser/chromeos/login/login_performer.cc
@@ -4,41 +4,88 @@
#include "chrome/browser/chromeos/login/login_performer.h"
+#include <string>
+
+#include "app/l10n_util.h"
+#include "app/resource_bundle.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/chromeos/boot_times_loader.h"
+#include "chrome/browser/chromeos/cros/cros_library.h"
+#include "chrome/browser/chromeos/cros/screen_lock_library.h"
#include "chrome/browser/chromeos/login/login_utils.h"
+#include "chrome/browser/chromeos/login/screen_locker.h"
#include "chrome/browser/chromeos/user_cros_settings_provider.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/profile_manager.h"
+#include "grit/generated_resources.h"
namespace chromeos {
-namespace {
-} // namespace
+// Initialize default LoginPerformer.
+// static
+LoginPerformer* LoginPerformer::default_performer_ = NULL;
LoginPerformer::LoginPerformer(Delegate* delegate)
: last_login_failure_(LoginFailure::None()),
- delegate_(delegate) {}
+ delegate_(delegate),
+ password_changed_(false) {
+ 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
+ default_performer_ = this;
+}
+
+LoginPerformer::~LoginPerformer() {
+ 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.
+ default_performer_ = NULL;
+}
////////////////////////////////////////////////////////////////////////////////
// LoginPerformer, LoginStatusConsumer implementation:
void LoginPerformer::OnLoginFailure(const LoginFailure& failure) {
- last_login_failure_ = failure;
- if (delegate_) {
- captcha_.clear();
- captcha_token_.clear();
- if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED &&
- failure.error().state() == GoogleServiceAuthError::CAPTCHA_REQUIRED) {
- captcha_token_ = failure.error().captcha().token;
- }
- delegate_->OnLoginFailure(failure);
- } else {
- // TODO(nkostylev): Provide blocking UI using ScreenLocker.
- }
+ DVLOG(1) << "failure.reason " << failure.reason();
+ DVLOG(1) << "failure.error.state " << failure.error().state();
+
+ last_login_failure_ = failure;
+ if (delegate_) {
+ captcha_.clear();
+ captcha_token_.clear();
+ if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED &&
+ failure.error().state() == GoogleServiceAuthError::CAPTCHA_REQUIRED) {
+ captcha_token_ = failure.error().captcha().token;
+ }
+ delegate_->OnLoginFailure(failure);
+ return;
+ }
+
+ // Consequent online login failure with blocking UI on.
+ // No difference between cases whether screen was locked by the user or
+ // by LoginPerformer.
+ // Display recoverable error message using ScreenLocker,
+ // force sign out otherwise.
+ if (ScreenLocker::default_screen_locker()) {
+ ResolveLockLoginFailure();
+ return;
+ }
+
+ // Offline auth - OK, online auth - failed.
+ if (failure.reason() == LoginFailure::NETWORK_AUTH_FAILED) {
+ ResolveInitialNetworkAuthFailure();
+ } else if (failure.reason() == LoginFailure::LOGIN_TIMED_OUT) {
+ LOG(INFO) << "Online login timed out. "
+ << "Granting user access based on offline auth only.";
+ MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ } else {
+ // COULD_NOT_MOUNT_CRYPTOHOME, COULD_NOT_MOUNT_TMPFS:
+ // happens during offline auth only.
+ // UNLOCK_FAILED is used during normal screen lock case.
+ // TODO(nkostylev) DATA_REMOVAL_FAILED - ?
+ NOTREACHED();
+ }
}
void LoginPerformer::OnLoginSuccess(
@@ -46,6 +93,7 @@ void LoginPerformer::OnLoginSuccess(
const std::string& password,
const GaiaAuthConsumer::ClientLoginResult& credentials,
bool pending_requests) {
+ VLOG(1) << "LoginSuccess, pending_requests " << pending_requests;
if (delegate_) {
delegate_->OnLoginSuccess(username,
password,
@@ -54,8 +102,15 @@ void LoginPerformer::OnLoginSuccess(
if (!pending_requests)
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
} else {
- DCHECK(!pending_requests);
- // Online login has succeeded. Delete our instance.
+ //DCHECK(!pending_requests);
+ // Online login has succeeded.
+ // TODO(nkostylev): Execute CookieFetcher->AttemptFetch() here once
+ // async login is implemented - waiting for CL merge.
+ if (ScreenLocker::default_screen_locker()) {
+ DVLOG(1) << "Online login OK - unlocking screen.";
+ RequestScreenUnlock();
+ return;
+ }
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
}
@@ -73,7 +128,12 @@ void LoginPerformer::OnPasswordChangeDetected(
if (delegate_) {
delegate_->OnPasswordChangeDetected(credentials);
} else {
- // TODO(nkostylev): Provide blocking UI using ScreenLocker.
+ last_login_failure_ =
+ LoginFailure::FromNetworkAuthFailure(GoogleServiceAuthError(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS));
+ password_changed_ = true;
+ DVLOG(1) << "Password change detected - locking screen.";
+ RequestScreenLock();
}
}
@@ -94,13 +154,32 @@ void LoginPerformer::OnCheckWhiteListCompleted(bool success,
}
////////////////////////////////////////////////////////////////////////////////
+// LoginPerformer, NotificationObserver implementation:
+//
+
+void LoginPerformer::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ if (type != NotificationType::SCREEN_LOCK_STATE_CHANGED)
+ return;
+
+ bool is_screen_locked = *Details<bool>(details).ptr();
+ if (is_screen_locked)
+ ResolveScreenLocked();
+ else
+ ResolveScreenUnlocked();
+}
+
+////////////////////////////////////////////////////////////////////////////////
// LoginPerformer, public:
void LoginPerformer::Login(const std::string& username,
const std::string& password) {
username_ = username;
password_ = password;
- if (UserCrosSettingsProvider::cached_allow_new_user()) {
+ // Whitelist is performed during offline login only.
+ if (ScreenLocker::default_screen_locker() ||
+ UserCrosSettingsProvider::cached_allow_new_user()) {
// Starts authentication if guest login is allowed.
StartAuthentication();
} else {
@@ -140,19 +219,176 @@ void LoginPerformer::ResyncEncryptedData() {
////////////////////////////////////////////////////////////////////////////////
// LoginPerformer, private:
+void LoginPerformer::RequestScreenLock() {
+ DVLOG(1) << "Screen lock requested";
+ if (ScreenLocker::default_screen_locker()) {
+ DVLOG(1) << "Screen already locked";
+ ResolveScreenLocked();
+ } else {
+ registrar_.Add(
+ this,
+ NotificationType::SCREEN_LOCK_STATE_CHANGED,
+ NotificationService::AllSources());
+ chromeos::CrosLibrary::Get()->GetScreenLockLibrary()->
+ NotifyScreenLockRequested();
+ }
+}
+
+void LoginPerformer::RequestScreenUnlock() {
+ DVLOG(1) << "Screen unlock requested";
+ if (ScreenLocker::default_screen_locker()) {
+ chromeos::CrosLibrary::Get()->GetScreenLockLibrary()->
+ NotifyScreenUnlockRequested();
+ // Will unsubscribe from notifications once unlock is successful.
+ } else {
+ LOG(ERROR) << "Screen is not locked";
+ NOTREACHED();
+ }
+}
+
+void LoginPerformer::ResolveInitialNetworkAuthFailure() {
+ DVLOG(1) << "auth_error: " << last_login_failure_.error().state();
+
+ switch (last_login_failure_.error().state()) {
+ case GoogleServiceAuthError::CONNECTION_FAILED:
+ case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
+ case GoogleServiceAuthError::TWO_FACTOR:
+ case GoogleServiceAuthError::REQUEST_CANCELED:
+ // Offline auth already done. Online auth will be done next time
+ // or once user accesses web property.
+ LOG(INFO) << "Granting user access based on offline auth only. "
+ << "Online login failed with "
+ << last_login_failure_.error().state();
+ MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+ return;
+ case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
+ // Offline auth OK, so it might be the case of changed password.
+ password_changed_ = true;
+ case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
+ case GoogleServiceAuthError::ACCOUNT_DELETED:
+ case GoogleServiceAuthError::ACCOUNT_DISABLED:
+ // Access not granted. User has to sign out.
+ // Request screen lock & show error message there.
+ case GoogleServiceAuthError::CAPTCHA_REQUIRED:
+ // User is requested to enter CAPTCHA challenge.
+ RequestScreenLock();
+ return;
+ default:
+ // Unless there's new GoogleServiceAuthErrors state has been added.
+ NOTREACHED();
+ return;
+ }
+}
+
+void LoginPerformer::ResolveLockLoginFailure() {
+ if (last_login_failure_.reason() == LoginFailure::LOGIN_TIMED_OUT) {
+ LOG(INFO) << "Online login timed out - unlocking screen. "
+ << "Granting user access based on offline auth only.";
+ RequestScreenUnlock();
+ return;
+ } else if (last_login_failure_.reason() ==
+ LoginFailure::NETWORK_AUTH_FAILED) {
+ ResolveLockNetworkAuthFailure();
+ return;
+ } else if (last_login_failure_.reason() ==
+ LoginFailure::COULD_NOT_MOUNT_CRYPTOHOME ||
+ last_login_failure_.reason() ==
+ LoginFailure::DATA_REMOVAL_FAILED) {
+ LOG(ERROR) << "Cryptohome error, forcing sign out.";
+ } else {
+ // COULD_NOT_MOUNT_TMPFS, UNLOCK_FAILED should not happen here.
+ NOTREACHED();
+ }
+ ScreenLocker::default_screen_locker()->Signout();
+}
+
+void LoginPerformer::ResolveLockNetworkAuthFailure() {
+ DCHECK(ScreenLocker::default_screen_locker());
+ DCHECK(last_login_failure_.reason() == LoginFailure::NETWORK_AUTH_FAILED);
+
+ std::wstring msg;
+ bool sign_out_only = false;
+
+ DVLOG(1) << "auth_error: " << last_login_failure_.error().state();
+
+ switch (last_login_failure_.error().state()) {
+ case GoogleServiceAuthError::CONNECTION_FAILED:
+ case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
+ case GoogleServiceAuthError::TWO_FACTOR:
+ case GoogleServiceAuthError::REQUEST_CANCELED:
+ // Offline auth already done. Online auth will be done next time
+ // or once user accesses web property.
+ LOG(INFO) << "Granting user access based on offline auth only. "
+ << "Online login failed with "
+ << last_login_failure_.error().state();
+ RequestScreenUnlock();
+ return;
+ case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS:
+ // Password change detected.
+ msg = l10n_util::GetString(IDS_LOGIN_ERROR_PASSWORD_CHANGED);
+ break;
+ case GoogleServiceAuthError::USER_NOT_SIGNED_UP:
+ case GoogleServiceAuthError::ACCOUNT_DELETED:
+ case GoogleServiceAuthError::ACCOUNT_DISABLED:
+ // Access not granted. User has to sign out.
+ // Show error message using existing screen lock.
+ msg = l10n_util::GetString(IDS_LOGIN_ERROR_RESTRICTED);
+ sign_out_only = true;
+ break;
+ case GoogleServiceAuthError::CAPTCHA_REQUIRED:
+ // User is requested to enter CAPTCHA challenge.
+ msg = l10n_util::GetString(IDS_LOGIN_ERROR_AUTHENTICATING);
+ // TODO(nkostylev): Instruct ScreenLocker to show CAPTCHA input.
+ break;
+ default:
+ // Unless there's new GoogleServiceAuthError state has been added.
+ NOTREACHED();
+ break;
+ }
+
+ ScreenLocker::default_screen_locker()->ShowErrorMessage(msg, sign_out_only);
+}
+
+void LoginPerformer::ResolveScreenLocked() {
+ DVLOG(1) << "Screen locked";
+ ResolveLockNetworkAuthFailure();
+}
+
+void LoginPerformer::ResolveScreenUnlocked() {
+ DVLOG(1) << "Screen unlocked";
+ registrar_.RemoveAll();
+ MessageLoop::current()->DeleteSoon(FROM_HERE, this);
+}
+
void LoginPerformer::StartAuthentication() {
+ DVLOG(1) << "Auth started";
BootTimesLoader::Get()->AddLoginTimeMarker("AuthStarted", false);
- authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
Profile* profile = g_browser_process->profile_manager()->GetDefaultProfile();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(authenticator_.get(),
- &Authenticator::AuthenticateToLogin,
- profile,
- username_,
- password_,
- captcha_token_,
- captcha_));
+ if (delegate_) {
+ authenticator_ = LoginUtils::Get()->CreateAuthenticator(this);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(authenticator_.get(),
+ &Authenticator::AuthenticateToLogin,
+ profile,
+ username_,
+ password_,
+ captcha_token_,
+ captcha_));
+ } else {
+ DCHECK(authenticator_.get());
+ // At this point offline auth has been successful,
+ // retry online auth, using existing Authenticator instance.
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(authenticator_.get(),
+ &Authenticator::RetryAuth,
+ profile,
+ username_,
+ password_,
+ captcha_token_,
+ captcha_));
+ }
password_.clear();
}
« no previous file with comments | « chrome/browser/chromeos/login/login_performer.h ('k') | chrome/browser/chromeos/login/parallel_authenticator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698