OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/screen_locker.h" | 5 #include "chrome/browser/chromeos/login/screen_locker.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "ash/ash_switches.h" | 10 #include "ash/ash_switches.h" |
11 #include "ash/desktop_background/desktop_background_controller.h" | 11 #include "ash/desktop_background/desktop_background_controller.h" |
12 #include "ash/shell.h" | 12 #include "ash/shell.h" |
13 #include "ash/wm/session_state_controller.h" | 13 #include "ash/wm/session_state_controller.h" |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/command_line.h" | 15 #include "base/command_line.h" |
16 #include "base/lazy_instance.h" | 16 #include "base/lazy_instance.h" |
17 #include "base/memory/weak_ptr.h" | 17 #include "base/memory/weak_ptr.h" |
18 #include "base/message_loop.h" | 18 #include "base/message_loop.h" |
19 #include "base/metrics/histogram.h" | 19 #include "base/metrics/histogram.h" |
20 #include "base/string_util.h" | 20 #include "base/string_util.h" |
21 #include "base/timer.h" | 21 #include "base/timer.h" |
22 #include "base/utf_string_conversions.h" | |
23 #include "chrome/browser/chromeos/login/authenticator.h" | 22 #include "chrome/browser/chromeos/login/authenticator.h" |
24 #include "chrome/browser/chromeos/login/login_performer.h" | 23 #include "chrome/browser/chromeos/login/login_performer.h" |
25 #include "chrome/browser/chromeos/login/login_utils.h" | 24 #include "chrome/browser/chromeos/login/login_utils.h" |
26 #include "chrome/browser/chromeos/login/user_adding_screen.h" | 25 #include "chrome/browser/chromeos/login/user_adding_screen.h" |
27 #include "chrome/browser/chromeos/login/user_manager.h" | 26 #include "chrome/browser/chromeos/login/user_manager.h" |
28 #include "chrome/browser/chromeos/login/webui_screen_locker.h" | 27 #include "chrome/browser/chromeos/login/webui_screen_locker.h" |
29 #include "chrome/browser/lifetime/application_lifetime.h" | 28 #include "chrome/browser/lifetime/application_lifetime.h" |
30 #include "chrome/browser/profiles/profile.h" | 29 #include "chrome/browser/profiles/profile.h" |
31 #include "chrome/browser/profiles/profile_manager.h" | 30 #include "chrome/browser/profiles/profile_manager.h" |
32 #include "chrome/browser/signin/signin_manager.h" | 31 #include "chrome/browser/signin/signin_manager.h" |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 } // namespace | 144 } // namespace |
146 | 145 |
147 namespace chromeos { | 146 namespace chromeos { |
148 | 147 |
149 // static | 148 // static |
150 ScreenLocker* ScreenLocker::screen_locker_ = NULL; | 149 ScreenLocker* ScreenLocker::screen_locker_ = NULL; |
151 | 150 |
152 ////////////////////////////////////////////////////////////////////////////// | 151 ////////////////////////////////////////////////////////////////////////////// |
153 // ScreenLocker, public: | 152 // ScreenLocker, public: |
154 | 153 |
155 ScreenLocker::ScreenLocker(const User& user) | 154 ScreenLocker::ScreenLocker(const UserList& users) |
156 : user_(user), | 155 : users_(users), |
157 // TODO(oshima): support auto login mode (this is not implemented yet) | |
158 // http://crosbug.com/1881 | |
159 unlock_on_input_(user_.email().empty()), | |
160 locked_(false), | 156 locked_(false), |
161 start_time_(base::Time::Now()), | 157 start_time_(base::Time::Now()), |
162 login_status_consumer_(NULL), | 158 login_status_consumer_(NULL), |
163 incorrect_passwords_count_(0), | 159 incorrect_passwords_count_(0), |
164 weak_factory_(this) { | 160 weak_factory_(this) { |
165 DCHECK(!screen_locker_); | 161 DCHECK(!screen_locker_); |
166 screen_locker_ = this; | 162 screen_locker_ = this; |
167 } | 163 } |
168 | 164 |
169 void ScreenLocker::Init() { | 165 void ScreenLocker::Init() { |
170 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); | 166 authenticator_ = LoginUtils::Get()->CreateAuthenticator(this); |
171 delegate_.reset(new WebUIScreenLocker(this)); | 167 delegate_.reset(new WebUIScreenLocker(this)); |
172 delegate_->LockScreen(unlock_on_input_); | 168 delegate_->LockScreen(); |
173 } | 169 } |
174 | 170 |
175 void ScreenLocker::OnLoginFailure(const LoginFailure& error) { | 171 void ScreenLocker::OnLoginFailure(const LoginFailure& error) { |
176 content::RecordAction(UserMetricsAction("ScreenLocker_OnLoginFailure")); | 172 content::RecordAction(UserMetricsAction("ScreenLocker_OnLoginFailure")); |
177 if (authentication_start_time_.is_null()) { | 173 if (authentication_start_time_.is_null()) { |
178 LOG(ERROR) << "Start time is not set at authentication failure"; | 174 LOG(ERROR) << "Start time is not set at authentication failure"; |
179 } else { | 175 } else { |
180 base::TimeDelta delta = base::Time::Now() - authentication_start_time_; | 176 base::TimeDelta delta = base::Time::Now() - authentication_start_time_; |
181 VLOG(1) << "Authentication failure: " << delta.InSecondsF() << " second(s)"; | 177 VLOG(1) << "Authentication failure: " << delta.InSecondsF() << " second(s)"; |
182 UMA_HISTOGRAM_TIMES("ScreenLocker.AuthenticationFailureTime", delta); | 178 UMA_HISTOGRAM_TIMES("ScreenLocker.AuthenticationFailureTime", delta); |
(...skipping 19 matching lines...) Expand all Loading... |
202 incorrect_passwords_count_ = 0; | 198 incorrect_passwords_count_ = 0; |
203 if (authentication_start_time_.is_null()) { | 199 if (authentication_start_time_.is_null()) { |
204 if (!user_context.username.empty()) | 200 if (!user_context.username.empty()) |
205 LOG(ERROR) << "Start time is not set at authentication success"; | 201 LOG(ERROR) << "Start time is not set at authentication success"; |
206 } else { | 202 } else { |
207 base::TimeDelta delta = base::Time::Now() - authentication_start_time_; | 203 base::TimeDelta delta = base::Time::Now() - authentication_start_time_; |
208 VLOG(1) << "Authentication success: " << delta.InSecondsF() << " second(s)"; | 204 VLOG(1) << "Authentication success: " << delta.InSecondsF() << " second(s)"; |
209 UMA_HISTOGRAM_TIMES("ScreenLocker.AuthenticationSuccessTime", delta); | 205 UMA_HISTOGRAM_TIMES("ScreenLocker.AuthenticationSuccessTime", delta); |
210 } | 206 } |
211 | 207 |
212 Profile* profile = ProfileManager::GetDefaultProfile(); | 208 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kMultiProfiles)) { |
213 if (profile && !user_context.password.empty()) { | 209 // TODO(dzhioev): It seems like this branch never executed and should be |
214 // We have a non-empty password, so notify listeners (such as the sync | 210 // removed before multi-profile enabling. |
215 // engine). | 211 Profile* profile = ProfileManager::GetDefaultProfile(); |
216 SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile); | 212 if (profile && !user_context.password.empty()) { |
217 DCHECK(signin); | 213 // We have a non-empty password, so notify listeners (such as the sync |
218 GoogleServiceSigninSuccessDetails details( | 214 // engine). |
219 signin->GetAuthenticatedUsername(), | 215 SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile); |
220 user_context.password); | 216 DCHECK(signin); |
221 content::NotificationService::current()->Notify( | 217 GoogleServiceSigninSuccessDetails details( |
222 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL, | 218 signin->GetAuthenticatedUsername(), |
223 content::Source<Profile>(profile), | 219 user_context.password); |
224 content::Details<const GoogleServiceSigninSuccessDetails>(&details)); | 220 content::NotificationService::current()->Notify( |
| 221 chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL, |
| 222 content::Source<Profile>(profile), |
| 223 content::Details<const GoogleServiceSigninSuccessDetails>(&details)); |
| 224 } |
| 225 } |
| 226 |
| 227 if (const User* user = UserManager::Get()->FindUser(user_context.username)) { |
| 228 if (!user->is_active()) |
| 229 UserManager::Get()->SwitchActiveUser(user_context.username); |
| 230 } else { |
| 231 NOTREACHED() << "Logged in user not found."; |
225 } | 232 } |
226 | 233 |
227 authentication_capture_.reset(new AuthenticationParametersCapture()); | 234 authentication_capture_.reset(new AuthenticationParametersCapture()); |
228 authentication_capture_->username = user_context.username; | 235 authentication_capture_->username = user_context.username; |
229 authentication_capture_->pending_requests = pending_requests; | 236 authentication_capture_->pending_requests = pending_requests; |
230 authentication_capture_->using_oauth = using_oauth; | 237 authentication_capture_->using_oauth = using_oauth; |
231 | 238 |
232 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 239 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
233 if (command_line->HasSwitch(ash::switches::kAshDisableNewLockAnimations)) { | 240 if (command_line->HasSwitch(ash::switches::kAshDisableNewLockAnimations)) { |
234 UnlockOnLoginSuccess(); | 241 UnlockOnLoginSuccess(); |
(...skipping 25 matching lines...) Expand all Loading... |
260 UserContext(authentication_capture_->username, | 267 UserContext(authentication_capture_->username, |
261 std::string(), // password | 268 std::string(), // password |
262 std::string()), // auth_code | 269 std::string()), // auth_code |
263 authentication_capture_->pending_requests, | 270 authentication_capture_->pending_requests, |
264 authentication_capture_->using_oauth); | 271 authentication_capture_->using_oauth); |
265 } | 272 } |
266 authentication_capture_.reset(); | 273 authentication_capture_.reset(); |
267 weak_factory_.InvalidateWeakPtrs(); | 274 weak_factory_.InvalidateWeakPtrs(); |
268 } | 275 } |
269 | 276 |
270 void ScreenLocker::Authenticate(const string16& password) { | 277 void ScreenLocker::Authenticate(const UserContext& user_context) { |
| 278 LOG_ASSERT(IsUserLoggedIn(user_context.username)) |
| 279 << "Invalid user trying to unlock."; |
271 authentication_start_time_ = base::Time::Now(); | 280 authentication_start_time_ = base::Time::Now(); |
272 delegate_->SetInputEnabled(false); | 281 delegate_->SetInputEnabled(false); |
273 delegate_->OnAuthenticate(); | 282 delegate_->OnAuthenticate(); |
274 | 283 |
275 // If LoginPerformer instance exists, | 284 BrowserThread::PostTask( |
276 // initial online login phase is still active. | 285 BrowserThread::UI, FROM_HERE, |
277 if (LoginPerformer::default_performer()) { | 286 base::Bind(&Authenticator::AuthenticateToUnlock, |
278 DVLOG(1) << "Delegating authentication to LoginPerformer."; | 287 authenticator_.get(), |
279 LoginPerformer::default_performer()->PerformLogin( | 288 user_context)); |
280 UserContext(user_.email(), | 289 } |
281 UTF16ToUTF8(password), | 290 |
282 std::string()), // auth_code | 291 void ScreenLocker::AuthenticateByPassword(const std::string& password) { |
283 LoginPerformer::AUTH_MODE_INTERNAL); | 292 LOG_ASSERT(users_.size() == 1); |
284 } else { | 293 Authenticate(UserContext(users_[0]->email(), password, "")); |
285 BrowserThread::PostTask( | |
286 BrowserThread::UI, FROM_HERE, | |
287 base::Bind(&Authenticator::AuthenticateToUnlock, authenticator_.get(), | |
288 UserContext(user_.email(), | |
289 UTF16ToUTF8(password), | |
290 std::string()))); // auth_code | |
291 } | |
292 } | 294 } |
293 | 295 |
294 void ScreenLocker::ClearErrors() { | 296 void ScreenLocker::ClearErrors() { |
295 delegate_->ClearErrors(); | 297 delegate_->ClearErrors(); |
296 } | 298 } |
297 | 299 |
298 void ScreenLocker::EnableInput() { | 300 void ScreenLocker::EnableInput() { |
299 delegate_->SetInputEnabled(true); | 301 delegate_->SetInputEnabled(true); |
300 } | 302 } |
301 | 303 |
(...skipping 21 matching lines...) Expand all Loading... |
323 } | 325 } |
324 | 326 |
325 // static | 327 // static |
326 void ScreenLocker::Show() { | 328 void ScreenLocker::Show() { |
327 content::RecordAction(UserMetricsAction("ScreenLocker_Show")); | 329 content::RecordAction(UserMetricsAction("ScreenLocker_Show")); |
328 DCHECK(base::MessageLoop::current()->type() == base::MessageLoop::TYPE_UI); | 330 DCHECK(base::MessageLoop::current()->type() == base::MessageLoop::TYPE_UI); |
329 | 331 |
330 // Check whether the currently logged in user is a guest account and if so, | 332 // Check whether the currently logged in user is a guest account and if so, |
331 // refuse to lock the screen (crosbug.com/23764). | 333 // refuse to lock the screen (crosbug.com/23764). |
332 // For a demo user, we should never show the lock screen (crosbug.com/27647). | 334 // For a demo user, we should never show the lock screen (crosbug.com/27647). |
333 // TODO(flackr): We can allow lock screen for guest accounts when | |
334 // unlock_on_input is supported by the WebUI screen locker. | |
335 if (UserManager::Get()->IsLoggedInAsGuest() || | 335 if (UserManager::Get()->IsLoggedInAsGuest() || |
336 UserManager::Get()->IsLoggedInAsDemoUser()) { | 336 UserManager::Get()->IsLoggedInAsDemoUser()) { |
337 VLOG(1) << "Refusing to lock screen for guest/demo account"; | 337 VLOG(1) << "Refusing to lock screen for guest/demo account"; |
338 return; | 338 return; |
339 } | 339 } |
340 | 340 |
341 // Exit fullscreen. | 341 // Exit fullscreen. |
342 Browser* browser = chrome::FindLastActiveWithHostDesktopType( | 342 Browser* browser = chrome::FindLastActiveWithHostDesktopType( |
343 chrome::HOST_DESKTOP_TYPE_ASH); | 343 chrome::HOST_DESKTOP_TYPE_ASH); |
344 // browser can be NULL if we receive a lock request before the first browser | 344 // browser can be NULL if we receive a lock request before the first browser |
345 // window is shown. | 345 // window is shown. |
346 if (browser && browser->window()->IsFullscreen()) { | 346 if (browser && browser->window()->IsFullscreen()) { |
347 chrome::ToggleFullscreenMode(browser); | 347 chrome::ToggleFullscreenMode(browser); |
348 } | 348 } |
349 | 349 |
350 if (!screen_locker_) { | 350 if (!screen_locker_) { |
351 ScreenLocker* locker = | 351 ScreenLocker* locker = |
352 new ScreenLocker(*UserManager::Get()->GetLoggedInUser()); | 352 new ScreenLocker(UserManager::Get()->GetLRULoggedInUsers()); |
353 VLOG(1) << "Created ScreenLocker " << locker; | 353 VLOG(1) << "Created ScreenLocker " << locker; |
354 locker->Init(); | 354 locker->Init(); |
355 } else { | 355 } else { |
356 VLOG(1) << "ScreenLocker " << screen_locker_ << " already exists; " | 356 VLOG(1) << "ScreenLocker " << screen_locker_ << " already exists; " |
357 << " calling session manager's HandleLockScreenShown D-Bus method"; | 357 << " calling session manager's HandleLockScreenShown D-Bus method"; |
358 DBusThreadManager::Get()->GetSessionManagerClient()-> | 358 DBusThreadManager::Get()->GetSessionManagerClient()-> |
359 NotifyLockScreenShown(); | 359 NotifyLockScreenShown(); |
360 } | 360 } |
361 } | 361 } |
362 | 362 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
441 content::Source<ScreenLocker>(this), | 441 content::Source<ScreenLocker>(this), |
442 content::Details<bool>(&state)); | 442 content::Details<bool>(&state)); |
443 VLOG(1) << "Calling session manager's HandleLockScreenShown D-Bus method"; | 443 VLOG(1) << "Calling session manager's HandleLockScreenShown D-Bus method"; |
444 DBusThreadManager::Get()->GetSessionManagerClient()->NotifyLockScreenShown(); | 444 DBusThreadManager::Get()->GetSessionManagerClient()->NotifyLockScreenShown(); |
445 } | 445 } |
446 | 446 |
447 content::WebUI* ScreenLocker::GetAssociatedWebUI() { | 447 content::WebUI* ScreenLocker::GetAssociatedWebUI() { |
448 return delegate_->GetAssociatedWebUI(); | 448 return delegate_->GetAssociatedWebUI(); |
449 } | 449 } |
450 | 450 |
| 451 bool ScreenLocker::IsUserLoggedIn(const std::string& username) { |
| 452 for (UserList::const_iterator it = users_.begin(); it != users_.end(); ++it) { |
| 453 if ((*it)->email() == username) |
| 454 return true; |
| 455 } |
| 456 return false; |
| 457 } |
| 458 |
451 } // namespace chromeos | 459 } // namespace chromeos |
| 460 |
OLD | NEW |