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 |