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

Side by Side 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: remove debug logging 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 unified diff | Download patch
OLDNEW
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);
38 default_performer_ = this;
39 }
40
41 LoginPerformer::~LoginPerformer() {
42 DVLOG(1) << "Deleting LoginPerformer";
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);
whywhat 2010/11/25 15:40:37 I thought delegate_ owns login performer if it exi
Nikita (slow) 2010/11/29 11:20:25 No, when delegate_->OnLoginSuccess is executed. De
56 } else { 104 } else {
57 DCHECK(!pending_requests); 105 //DCHECK(!pending_requests);
whywhat 2010/11/25 15:40:37 Remove or uncomment?
Nikita (slow) 2010/11/29 11:20:25 Done.
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;
whywhat 2010/11/25 15:40:37 Shouldn't LP delete itself here?
Nikita (slow) 2010/11/29 11:20:25 Not yet, added comment. Checked other DeleteSoon c
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.
whywhat 2010/11/25 15:40:37 Whitelist -> Whitelist check
Nikita (slow) 2010/11/29 11:20:25 Done.
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698