summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authornkostylev@chromium.org <nkostylev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-02 15:50:04 +0000
committernkostylev@chromium.org <nkostylev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-02 15:50:04 +0000
commit9ac20a5c0374c5a4c7e190ecb6e1aeb183af51a6 (patch)
treec7c50d54f23f794f171fdf4b09f1332a4d45fa30 /chrome/browser
parentb5123fe23a4d0f3b72d65e7e4f33a795b172d78d (diff)
downloadchromium_src-9ac20a5c0374c5a4c7e190ecb6e1aeb183af51a6.zip
chromium_src-9ac20a5c0374c5a4c7e190ecb6e1aeb183af51a6.tar.gz
chromium_src-9ac20a5c0374c5a4c7e190ecb6e1aeb183af51a6.tar.bz2
[cros] Add blocking UI on offline: OK, online auth: fail case.
Using ParallelAuthenticator to test http://codereview.chromium.org/3442009 BUG=chromium-os:6638 TEST=manual Review URL: http://codereview.chromium.org/3583013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@68013 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/chromeos/login/login_performer.cc347
-rw-r--r--chrome/browser/chromeos/login/login_performer.h92
-rw-r--r--chrome/browser/chromeos/login/parallel_authenticator.cc4
-rw-r--r--chrome/browser/chromeos/login/password_changed_view.cc10
-rw-r--r--chrome/browser/chromeos/login/password_changed_view.h4
-rw-r--r--chrome/browser/chromeos/login/screen_locker.cc85
-rw-r--r--chrome/browser/chromeos/login/screen_locker.h15
7 files changed, 465 insertions, 92 deletions
diff --git a/chrome/browser/chromeos/login/login_performer.cc b/chrome/browser/chromeos/login/login_performer.cc
index 1f10bfb..4c5749b 100644
--- a/chrome/browser/chromeos/login/login_performer.cc
+++ b/chrome/browser/chromeos/login/login_performer.cc
@@ -4,42 +4,93 @@
#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),
- method_factory_(this) {}
+ password_changed_(false),
+ screen_lock_requested_(false),
+ method_factory_(this) {
+ DCHECK(default_performer_ == NULL)
+ << "LoginPerformer should have only one instance.";
+ default_performer_ = this;
+}
+
+LoginPerformer::~LoginPerformer() {
+ DVLOG(1) << "Deleting LoginPerformer";
+ DCHECK(default_performer_ != NULL) << "Default instance should exist.";
+ 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) {
+ VLOG(1) << "Online login timed out. "
+ << "Granting user access based on offline auth only.";
+ // ScreenLock is not active, it's ok to delete itself.
+ 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(
@@ -47,16 +98,35 @@ 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,
credentials,
pending_requests);
+ // After delegate_->OnLoginSuccess(...) is called, delegate_ releases
+ // LoginPerformer ownership. LP now manages it's lifetime on its own.
+ // 2 things could make it exist longer:
+ // 1. ScreenLock active (pending correct new password input)
+ // 2. Pending online auth request.
if (!pending_requests)
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
} else {
- DCHECK(!pending_requests);
- // Online login has succeeded. Delete our instance.
+ DCHECK(!pending_requests)
+ << "Pending request w/o delegate_ should not happen!";
+ // Online login has succeeded.
+ // TODO(nkostylev): Execute CookieFetcher->AttemptFetch() here once
+ // async login is implemented.
+ // http://crosbug.com/9814
+ if (ScreenLocker::default_screen_locker()) {
+ DVLOG(1) << "Online login OK - unlocking screen.";
+ RequestScreenUnlock();
+ // Do not delete itself just yet, wait for unlock.
+ // See ResolveScreenUnlocked().
+ return;
+ }
+ // There's nothing else that's holding LP from deleting itself -
+ // no ScreenLock, no pending requests.
MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
}
@@ -74,7 +144,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();
}
}
@@ -95,26 +170,53 @@ 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) {
+ if (screen_lock_requested_) {
+ screen_lock_requested_ = false;
+ ResolveScreenLocked();
+ }
+ } else {
+ ResolveScreenUnlocked();
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
// LoginPerformer, public:
void LoginPerformer::Login(const std::string& username,
const std::string& password) {
username_ = username;
password_ = password;
- // Must not proceed without signature verification.
- UserCrosSettingsProvider user_settings;
- bool trusted_setting_available = user_settings.RequestTrustedAllowNewUser(
- method_factory_.NewRunnableMethod(
- &LoginPerformer::Login,
- username,
- password));
- if (!trusted_setting_available) {
- // Value of AllowNewUser setting is still not verified.
- // Another attempt will be invoked after verification completion.
- return;
+
+ // Whitelist check is always performed during initial login and
+ // should not be performed when ScreenLock is active (pending online auth).
+ if (!ScreenLocker::default_screen_locker()) {
+ // Must not proceed without signature verification.
+ UserCrosSettingsProvider user_settings;
+ bool trusted_setting_available = user_settings.RequestTrustedAllowNewUser(
+ method_factory_.NewRunnableMethod(&LoginPerformer::Login,
+ username,
+ password));
+ if (!trusted_setting_available) {
+ // Value of AllowNewUser setting is still not verified.
+ // Another attempt will be invoked after verification completion.
+ return;
+ }
}
- if (UserCrosSettingsProvider::cached_allow_new_user()) {
- // Starts authentication if guest login is allowed.
+
+ if (ScreenLocker::default_screen_locker() ||
+ UserCrosSettingsProvider::cached_allow_new_user()) {
+ // Starts authentication if guest login is allowed or online auth pending.
StartAuthentication();
} else {
// Otherwise, do whitelist check first.
@@ -153,19 +255,182 @@ 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 {
+ screen_lock_requested_ = true;
+ 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.
+ VLOG(1) << "Granting user access based on offline auth only. "
+ << "Online login failed with "
+ << last_login_failure_.error().state();
+ // Resolving initial online auth failure, no ScreenLock is active.
+ 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(WARNING) << "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())
+ << "ScreenLocker instance doesn't exist.";
+ 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(WARNING) << "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.
+ // http://crosbug.com/9812
+ 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();
+ // If screen was unlocked that was for a reason, should delete itself now.
+ 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())
+ << "Authenticator instance doesn't exist for login attempt retry.";
+ // 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();
}
diff --git a/chrome/browser/chromeos/login/login_performer.h b/chrome/browser/chromeos/login/login_performer.h
index 7edf3cf..c67a173 100644
--- a/chrome/browser/chromeos/login/login_performer.h
+++ b/chrome/browser/chromeos/login/login_performer.h
@@ -15,22 +15,44 @@
#include "chrome/browser/chromeos/login/login_status_consumer.h"
#include "chrome/browser/chromeos/login/signed_settings_helper.h"
#include "chrome/common/net/gaia/google_service_auth_error.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
namespace chromeos {
// This class encapsulates sign in operations.
-// Sign in is performed in a way that offline login is executed first.
-// Once it's successful user homedir is mounted, UI is launched.
-// If concurrent online login operation would fail that means:
-// - User password has changed. Ask user for the new password.
-// - User password has changed & CAPTCHA input is required.
-// If |delegate_| is not NULL it will handle
-// password changed and CAPTCHA dialogs.
+// Sign in is performed in a way that offline auth is executed first.
+// Once offline auth is OK - user homedir is mounted, UI is launched.
+// At this point LoginPerformer |delegate_| is destroyed and it releases
+// LP instance ownership. LP waits for online login result.
+// If auth is succeeded, cookie fetcher is executed, LP instance deletes itself.
+//
+// If online login operation fails that means:
+// (1) User password has changed. Ask user for the new password.
+// (2) User password has changed and/or CAPTCHA input is required.
+// (3) User account is deleted/disabled/not signed up.
+// (4) Timeout/service unavailable/connection failed.
+//
+// Actions:
+// (1)-(3): Request screen lock.
+// (1) Ask for new user password.
+// (2) Ask for new user password and/or CAPTCHA.
+// (3) Display error message and allow "Sign Out" as the only action.
+// (4) Delete LP instance since offline auth was OK.
+//
+// If |delegate_| is not NULL it will handle error messages,
+// CAPTCHA dialog, password input.
// If |delegate_| is NULL that does mean that LoginPerformer instance
-// is waiting for online login operation.
-// In case of failure use ScreenLock and ask for a new password.
+// is waiting for successful online login or blocked on online login failure.
+// In case of failure password/captcha
+// input & error messages display is dedicated to ScreenLocker instance.
+//
+// 2 things make LoginPerfrormer instance exist longer:
+// 1. ScreenLock active (pending correct new password input)
+// 2. Pending online auth request.
class LoginPerformer : public LoginStatusConsumer,
- public SignedSettingsHelper::Callback {
+ public SignedSettingsHelper::Callback,
+ public NotificationObserver {
public:
// Delegate class to get notifications from the LoginPerformer.
class Delegate : public LoginStatusConsumer {
@@ -40,6 +62,14 @@ class LoginPerformer : public LoginStatusConsumer,
};
explicit LoginPerformer(Delegate* delegate);
+ virtual ~LoginPerformer();
+
+ // Returns the default instance if it has been created.
+ // This instance is owned by delegate_ till it's destroyed.
+ // When LP instance lives by itself it's used by ScreenLocker instance.
+ static LoginPerformer* default_performer() {
+ return default_performer_;
+ }
// LoginStatusConsumer implementation:
virtual void OnLoginFailure(const LoginFailure& error);
@@ -52,10 +82,15 @@ class LoginPerformer : public LoginStatusConsumer,
virtual void OnPasswordChangeDetected(
const GaiaAuthConsumer::ClientLoginResult& credentials);
- // SignedSettingsHelper::Callback
+ // SignedSettingsHelper::Callback implementation:
virtual void OnCheckWhiteListCompleted(bool success,
const std::string& email);
+ // NotificationObserver implementation:
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
// Performs login with the |username| and |password| specified.
void Login(const std::string& username, const std::string& password);
@@ -82,9 +117,33 @@ class LoginPerformer : public LoginStatusConsumer,
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
private:
+ // Requests screen lock and subscribes to screen lock notifications.
+ void RequestScreenLock();
+
+ // Requests screen unlock.
+ void RequestScreenUnlock();
+
+ // Resolves initial LoginFailure::NETWORK_AUTH_FAILED error i.e.
+ // when screen is not locked yet.
+ void ResolveInitialNetworkAuthFailure();
+
+ // Resolves LoginFailure when screen is locked.
+ void ResolveLockLoginFailure();
+
+ // Resolves LoginFailure::NETWORK_AUTH_FAILED error when screen is locked.
+ // Uses ScreenLocker to show error message based on |last_login_failure_|.
+ void ResolveLockNetworkAuthFailure();
+
+ // Resolve ScreenLock changed state.
+ void ResolveScreenLocked();
+ void ResolveScreenUnlocked();
+
// Starts authentication.
void StartAuthentication();
+ // Default performer. Will be used by ScreenLocker.
+ static LoginPerformer* default_performer_;
+
// Used for logging in.
scoped_refptr<Authenticator> authenticator_;
@@ -108,6 +167,17 @@ class LoginPerformer : public LoginStatusConsumer,
// Notifications receiver.
Delegate* delegate_;
+ // True if password change has been detected.
+ // Once correct password is entered homedir migration is executed.
+ bool password_changed_;
+
+ // Used for ScreenLock notifications.
+ NotificationRegistrar registrar_;
+
+ // True if LoginPerformer has requested screen lock. Used to distinguish
+ // such requests with cases when screen is locked on its own.
+ bool screen_lock_requested_;
+
ScopedRunnableMethodFactory<LoginPerformer> method_factory_;
DISALLOW_COPY_AND_ASSIGN(LoginPerformer);
diff --git a/chrome/browser/chromeos/login/parallel_authenticator.cc b/chrome/browser/chromeos/login/parallel_authenticator.cc
index ec499fb..27b7186 100644
--- a/chrome/browser/chromeos/login/parallel_authenticator.cc
+++ b/chrome/browser/chromeos/login/parallel_authenticator.cc
@@ -273,7 +273,9 @@ void ParallelAuthenticator::Resolve() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
bool request_pending = false;
bool create = false;
- switch (ResolveState()) {
+ ParallelAuthenticator::AuthState state = ResolveState();
+ VLOG(1) << "Resolved state to: " << state;
+ switch (state) {
case CONTINUE:
case POSSIBLE_PW_CHANGE:
case NO_MOUNT:
diff --git a/chrome/browser/chromeos/login/password_changed_view.cc b/chrome/browser/chromeos/login/password_changed_view.cc
index 22f953f..5a1d2d0 100644
--- a/chrome/browser/chromeos/login/password_changed_view.cc
+++ b/chrome/browser/chromeos/login/password_changed_view.cc
@@ -183,14 +183,4 @@ void PasswordChangedView::ButtonPressed(Button* sender,
}
}
-bool PasswordChangedView::HandleKeystroke(views::Textfield* s,
- const views::Textfield::Keystroke& keystroke) {
- if (keystroke.GetKeyboardCode() == app::VKEY_RETURN) {
- ExitDialog();
- return true;
- }
-
- return false;
-}
-
} // namespace chromeos
diff --git a/chrome/browser/chromeos/login/password_changed_view.h b/chrome/browser/chromeos/login/password_changed_view.h
index b7d45da..706e53b 100644
--- a/chrome/browser/chromeos/login/password_changed_view.h
+++ b/chrome/browser/chromeos/login/password_changed_view.h
@@ -63,7 +63,9 @@ class PasswordChangedView : public views::View,
// views::Textfield::Controller overrides:
virtual bool HandleKeystroke(views::Textfield* sender,
- const views::Textfield::Keystroke& keystroke);
+ const views::Textfield::Keystroke& keystroke) {
+ return false;
+ }
virtual void ContentsChanged(views::Textfield* sender,
const string16& new_contents) {}
diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc
index 87a28dd..6a753a9 100644
--- a/chrome/browser/chromeos/login/screen_locker.cc
+++ b/chrome/browser/chromeos/login/screen_locker.cc
@@ -32,6 +32,7 @@
#include "chrome/browser/chromeos/language_preferences.h"
#include "chrome/browser/chromeos/login/authenticator.h"
#include "chrome/browser/chromeos/login/background_view.h"
+#include "chrome/browser/chromeos/login/login_performer.h"
#include "chrome/browser/chromeos/login/login_utils.h"
#include "chrome/browser/chromeos/login/message_bubble.h"
#include "chrome/browser/chromeos/login/screen_lock_view.h"
@@ -725,14 +726,7 @@ void ScreenLocker::OnLoginFailure(const LoginFailure& error) {
EnableInput();
// Don't enable signout button here as we're showing
// MessageBubble.
- gfx::Rect rect = screen_lock_view_->GetPasswordBoundsRelativeTo(
- lock_widget_->GetRootView());
- gfx::Rect lock_widget_bounds;
- lock_widget_->GetBounds(&lock_widget_bounds, false);
- rect.Offset(lock_widget_bounds.x(), lock_widget_bounds.y());
- if (error_info_)
- error_info_->Close();
std::wstring msg = l10n_util::GetString(IDS_LOGIN_ERROR_AUTHENTICATING);
const std::string error_text = error.GetErrorString();
if (!error_text.empty())
@@ -743,21 +737,7 @@ void ScreenLocker::OnLoginFailure(const LoginFailure& error) {
if (input_method_library->GetNumActiveInputMethods() > 1)
msg += L"\n" + l10n_util::GetString(IDS_LOGIN_ERROR_KEYBOARD_SWITCH_HINT);
- error_info_ = MessageBubble::ShowNoGrab(
- lock_window_,
- rect,
- BubbleBorder::BOTTOM_LEFT,
- ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
- msg,
- std::wstring(), // TODO: add help link
- this);
- if (mouse_event_relay_.get()) {
- MessageLoopForUI::current()->RemoveObserver(mouse_event_relay_.get());
- }
- mouse_event_relay_.reset(
- new MouseEventRelay(lock_widget_->GetNativeView()->window,
- error_info_->GetNativeView()->window));
- MessageLoopForUI::current()->AddObserver(mouse_event_relay_.get());
+ ShowErrorBubble(msg, BubbleBorder::BOTTOM_LEFT);
}
void ScreenLocker::OnLoginSuccess(
@@ -801,12 +781,21 @@ void ScreenLocker::Authenticate(const string16& password) {
authentication_start_time_ = base::Time::Now();
screen_lock_view_->SetEnabled(false);
screen_lock_view_->SetSignoutEnabled(false);
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(authenticator_.get(),
- &Authenticator::AuthenticateToUnlock,
- user_.email(),
- UTF16ToUTF8(password)));
+
+ // If LoginPerformer instance exists,
+ // initial online login phase is still active.
+ if (LoginPerformer::default_performer()) {
+ DVLOG(1) << "Delegating authentication to LoginPerformer.";
+ LoginPerformer::default_performer()->Login(user_.email(),
+ UTF16ToUTF8(password));
+ } else {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(authenticator_.get(),
+ &Authenticator::AuthenticateToUnlock,
+ user_.email(),
+ UTF16ToUTF8(password)));
+ }
}
void ScreenLocker::ClearErrors() {
@@ -835,6 +824,19 @@ void ScreenLocker::Signout() {
}
}
+void ScreenLocker::ShowErrorMessage(const std::wstring& message,
+ bool sign_out_only) {
+ if (sign_out_only) {
+ screen_lock_view_->SetEnabled(false);
+ } else {
+ EnableInput();
+ }
+ screen_lock_view_->SetSignoutEnabled(sign_out_only);
+ // Make sure that active Sign Out button is not hidden behind the bubble.
+ ShowErrorBubble(message, sign_out_only ?
+ BubbleBorder::BOTTOM_RIGHT : BubbleBorder::BOTTOM_LEFT);
+}
+
void ScreenLocker::OnGrabInputs() {
DVLOG(1) << "OnGrabInputs";
input_grabbed_ = true;
@@ -980,6 +982,33 @@ void ScreenLocker::OnWindowManagerReady() {
ScreenLockReady();
}
+void ScreenLocker::ShowErrorBubble(const std::wstring& message,
+ BubbleBorder::ArrowLocation arrow_location) {
+ if (error_info_)
+ error_info_->Close();
+
+ gfx::Rect rect = screen_lock_view_->GetPasswordBoundsRelativeTo(
+ lock_widget_->GetRootView());
+ gfx::Rect lock_widget_bounds;
+ lock_widget_->GetBounds(&lock_widget_bounds, false);
+ rect.Offset(lock_widget_bounds.x(), lock_widget_bounds.y());
+ error_info_ = MessageBubble::ShowNoGrab(
+ lock_window_,
+ rect,
+ arrow_location,
+ ResourceBundle::GetSharedInstance().GetBitmapNamed(IDR_WARNING),
+ message,
+ std::wstring(), // TODO(nkostylev): Add help link.
+ this);
+
+ if (mouse_event_relay_.get())
+ MessageLoopForUI::current()->RemoveObserver(mouse_event_relay_.get());
+ mouse_event_relay_.reset(
+ new MouseEventRelay(lock_widget_->GetNativeView()->window,
+ error_info_->GetNativeView()->window));
+ MessageLoopForUI::current()->AddObserver(mouse_event_relay_.get());
+}
+
void ScreenLocker::StopScreenSaver() {
if (background_view_->IsScreenSaverVisible()) {
VLOG(1) << "StopScreenSaver";
diff --git a/chrome/browser/chromeos/login/screen_locker.h b/chrome/browser/chromeos/login/screen_locker.h
index 853c40f..27e1404 100644
--- a/chrome/browser/chromeos/login/screen_locker.h
+++ b/chrome/browser/chromeos/login/screen_locker.h
@@ -47,6 +47,11 @@ class ScreenLocker : public LoginStatusConsumer,
public:
explicit ScreenLocker(const UserManager::User& user);
+ // Returns the default instance if it has been created.
+ static ScreenLocker* default_screen_locker() {
+ return screen_locker_;
+ }
+
// Initialize and show the screen locker.
void Init();
@@ -76,6 +81,11 @@ class ScreenLocker : public LoginStatusConsumer,
// Exit the chrome, which will sign out the current session.
void Signout();
+ // Disables all UI needed and shows error bubble with |message|.
+ // If |sign_out_only| is true then all other input except "Sign Out"
+ // button is blocked.
+ void ShowErrorMessage(const std::wstring& message, bool sign_out_only);
+
// Called when the all inputs are grabbed.
void OnGrabInputs();
@@ -117,6 +127,11 @@ class ScreenLocker : public LoginStatusConsumer,
// Called when the window manager is ready to handle locked state.
void OnWindowManagerReady();
+ // Shows error_info_ bubble with the |message| and |arrow_location| specified.
+ // Assumes that UI controls were locked before that.
+ void ShowErrorBubble(const std::wstring& message,
+ BubbleBorder::ArrowLocation arrow_location);
+
// Stops screen saver.
void StopScreenSaver();