1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/webui/signin/user_manager_screen_handler.h" 6 7 #include "base/bind.h" 8 #include "base/prefs/pref_service.h" 9 #include "base/strings/utf_string_conversions.h" 10 #include "base/value_conversions.h" 11 #include "base/values.h" 12 #include "chrome/browser/browser_process.h" 13 #include "chrome/browser/chrome_notification_types.h" 14 #include "chrome/browser/extensions/api/screenlock_private/screenlock_private_api.h" 15 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile_avatar_icon_util.h" 17 #include "chrome/browser/profiles/profile_info_cache.h" 18 #include "chrome/browser/profiles/profile_info_cache_observer.h" 19 #include "chrome/browser/profiles/profile_manager.h" 20 #include "chrome/browser/profiles/profile_metrics.h" 21 #include "chrome/browser/profiles/profile_window.h" 22 #include "chrome/browser/profiles/profiles_state.h" 23 #include "chrome/browser/signin/local_auth.h" 24 #include "chrome/browser/ui/browser_dialogs.h" 25 #include "chrome/browser/ui/browser_finder.h" 26 #include "chrome/browser/ui/browser_list.h" 27 #include "chrome/browser/ui/chrome_pages.h" 28 #include "chrome/browser/ui/singleton_tabs.h" 29 #include "chrome/browser/ui/user_manager.h" 30 #include "chrome/common/pref_names.h" 31 #include "chrome/common/url_constants.h" 32 #include "chrome/grit/chromium_strings.h" 33 #include "chrome/grit/generated_resources.h" 34 #include "content/public/browser/notification_service.h" 35 #include "content/public/browser/web_contents.h" 36 #include "content/public/browser/web_ui.h" 37 #include "google_apis/gaia/gaia_auth_fetcher.h" 38 #include "google_apis/gaia/gaia_constants.h" 39 #include "third_party/skia/include/core/SkBitmap.h" 40 #include "ui/base/l10n/l10n_util.h" 41 #include "ui/base/resource/resource_bundle.h" 42 #include "ui/base/webui/web_ui_util.h" 43 #include "ui/gfx/image/image.h" 44 #include "ui/gfx/image/image_skia.h" 45 #include "ui/gfx/image/image_util.h" 46 47 namespace { 48 // User dictionary keys. 49 const char kKeyUsername[] = "username"; 50 const char kKeyDisplayName[]= "displayName"; 51 const char kKeyEmailAddress[] = "emailAddress"; 52 const char kKeyProfilePath[] = "profilePath"; 53 const char kKeyPublicAccount[] = "publicAccount"; 54 const char kKeySupervisedUser[] = "supervisedUser"; 55 const char kKeySignedIn[] = "signedIn"; 56 const char kKeyCanRemove[] = "canRemove"; 57 const char kKeyIsOwner[] = "isOwner"; 58 const char kKeyIsDesktop[] = "isDesktopUser"; 59 const char kKeyAvatarUrl[] = "userImage"; 60 const char kKeyNeedsSignin[] = "needsSignin"; 61 62 // JS API callback names. 63 const char kJsApiUserManagerInitialize[] = "userManagerInitialize"; 64 const char kJsApiUserManagerAddUser[] = "addUser"; 65 const char kJsApiUserManagerAuthLaunchUser[] = "authenticatedLaunchUser"; 66 const char kJsApiUserManagerLaunchGuest[] = "launchGuest"; 67 const char kJsApiUserManagerLaunchUser[] = "launchUser"; 68 const char kJsApiUserManagerRemoveUser[] = "removeUser"; 69 const char kJsApiUserManagerAttemptUnlock[] = "attemptUnlock"; 70 71 const size_t kAvatarIconSize = 180; 72 73 void HandleAndDoNothing(const base::ListValue* args) { 74 } 75 76 // This callback is run if the only profile has been deleted, and a new 77 // profile has been created to replace it. 78 void OpenNewWindowForProfile( 79 chrome::HostDesktopType desktop_type, 80 Profile* profile, 81 Profile::CreateStatus status) { 82 if (status != Profile::CREATE_STATUS_INITIALIZED) 83 return; 84 profiles::FindOrCreateNewWindowForProfile( 85 profile, 86 chrome::startup::IS_PROCESS_STARTUP, 87 chrome::startup::IS_FIRST_RUN, 88 desktop_type, 89 false); 90 } 91 92 std::string GetAvatarImageAtIndex( 93 size_t index, const ProfileInfoCache& info_cache) { 94 bool is_gaia_picture = 95 info_cache.IsUsingGAIAPictureOfProfileAtIndex(index) && 96 info_cache.GetGAIAPictureOfProfileAtIndex(index); 97 98 // If the avatar is too small (i.e. the old-style low resolution avatar), 99 // it will be pixelated when displayed in the User Manager, so we should 100 // return the placeholder avatar instead. 101 gfx::Image avatar_image = info_cache.GetAvatarIconOfProfileAtIndex(index); 102 if (avatar_image.Width() <= profiles::kAvatarIconWidth || 103 avatar_image.Height() <= profiles::kAvatarIconHeight ) { 104 avatar_image = ui::ResourceBundle::GetSharedInstance().GetImageNamed( 105 profiles::GetPlaceholderAvatarIconResourceID()); 106 } 107 gfx::Image resized_image = profiles::GetSizedAvatarIcon( 108 avatar_image, is_gaia_picture, kAvatarIconSize, kAvatarIconSize); 109 return webui::GetBitmapDataUrl(resized_image.AsBitmap()); 110 } 111 112 size_t GetIndexOfProfileWithEmailAndName(const ProfileInfoCache& info_cache, 113 const base::string16& email, 114 const base::string16& name) { 115 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) { 116 if (info_cache.GetUserNameOfProfileAtIndex(i) == email && 117 (name.empty() || 118 profiles::GetAvatarNameForProfile( 119 info_cache.GetPathOfProfileAtIndex(i)) == name)) { 120 return i; 121 } 122 } 123 return std::string::npos; 124 } 125 126 extensions::ScreenlockPrivateEventRouter* GetScreenlockRouter( 127 const std::string& email) { 128 ProfileInfoCache& info_cache = 129 g_browser_process->profile_manager()->GetProfileInfoCache(); 130 const size_t profile_index = GetIndexOfProfileWithEmailAndName( 131 info_cache, base::UTF8ToUTF16(email), base::string16()); 132 Profile* profile = g_browser_process->profile_manager() 133 ->GetProfileByPath(info_cache.GetPathOfProfileAtIndex(profile_index)); 134 return extensions::ScreenlockPrivateEventRouter::GetFactoryInstance()->Get( 135 profile); 136 } 137 138 bool IsGuestModeEnabled() { 139 PrefService* service = g_browser_process->local_state(); 140 DCHECK(service); 141 return service->GetBoolean(prefs::kBrowserGuestModeEnabled); 142 } 143 144 bool IsAddPersonEnabled() { 145 PrefService* service = g_browser_process->local_state(); 146 DCHECK(service); 147 return service->GetBoolean(prefs::kBrowserAddPersonEnabled); 148 } 149 150 } // namespace 151 152 // ProfileUpdateObserver ------------------------------------------------------ 153 154 class UserManagerScreenHandler::ProfileUpdateObserver 155 : public ProfileInfoCacheObserver { 156 public: 157 ProfileUpdateObserver( 158 ProfileManager* profile_manager, UserManagerScreenHandler* handler) 159 : profile_manager_(profile_manager), 160 user_manager_handler_(handler) { 161 DCHECK(profile_manager_); 162 DCHECK(user_manager_handler_); 163 profile_manager_->GetProfileInfoCache().AddObserver(this); 164 } 165 166 virtual ~ProfileUpdateObserver() { 167 DCHECK(profile_manager_); 168 profile_manager_->GetProfileInfoCache().RemoveObserver(this); 169 } 170 171 private: 172 // ProfileInfoCacheObserver implementation: 173 // If any change has been made to a profile, propagate it to all the 174 // visible user manager screens. 175 virtual void OnProfileAdded(const base::FilePath& profile_path) OVERRIDE { 176 user_manager_handler_->SendUserList(); 177 } 178 179 virtual void OnProfileWasRemoved( 180 const base::FilePath& profile_path, 181 const base::string16& profile_name) OVERRIDE { 182 // TODO(noms): Change 'SendUserList' to 'removeUser' JS-call when 183 // UserManager is able to find pod belonging to removed user. 184 user_manager_handler_->SendUserList(); 185 } 186 187 virtual void OnProfileNameChanged( 188 const base::FilePath& profile_path, 189 const base::string16& old_profile_name) OVERRIDE { 190 user_manager_handler_->SendUserList(); 191 } 192 193 virtual void OnProfileAvatarChanged( 194 const base::FilePath& profile_path) OVERRIDE { 195 user_manager_handler_->SendUserList(); 196 } 197 198 virtual void OnProfileSigninRequiredChanged( 199 const base::FilePath& profile_path) OVERRIDE { 200 user_manager_handler_->SendUserList(); 201 } 202 203 ProfileManager* profile_manager_; 204 205 UserManagerScreenHandler* user_manager_handler_; // Weak; owns us. 206 207 DISALLOW_COPY_AND_ASSIGN(ProfileUpdateObserver); 208 }; 209 210 // UserManagerScreenHandler --------------------------------------------------- 211 212 UserManagerScreenHandler::UserManagerScreenHandler() 213 : desktop_type_(chrome::GetActiveDesktop()), 214 weak_ptr_factory_(this) { 215 profileInfoCacheObserver_.reset( 216 new UserManagerScreenHandler::ProfileUpdateObserver( 217 g_browser_process->profile_manager(), this)); 218 } 219 220 UserManagerScreenHandler::~UserManagerScreenHandler() { 221 ScreenlockBridge::Get()->SetLockHandler(NULL); 222 } 223 224 void UserManagerScreenHandler::ShowBannerMessage( 225 const base::string16& message) { 226 web_ui()->CallJavascriptFunction( 227 "login.AccountPickerScreen.showBannerMessage", 228 base::StringValue(message)); 229 } 230 231 void UserManagerScreenHandler::ShowUserPodCustomIcon( 232 const std::string& user_email, 233 const ScreenlockBridge::UserPodCustomIconOptions& icon_options) { 234 scoped_ptr<base::DictionaryValue> icon = icon_options.ToDictionaryValue(); 235 if (!icon || icon->empty()) 236 return; 237 web_ui()->CallJavascriptFunction( 238 "login.AccountPickerScreen.showUserPodCustomIcon", 239 base::StringValue(user_email), 240 *icon); 241 } 242 243 void UserManagerScreenHandler::HideUserPodCustomIcon( 244 const std::string& user_email) { 245 web_ui()->CallJavascriptFunction( 246 "login.AccountPickerScreen.hideUserPodCustomIcon", 247 base::StringValue(user_email)); 248 } 249 250 void UserManagerScreenHandler::EnableInput() { 251 // Nothing here because UI is not disabled when starting to authenticate. 252 } 253 254 void UserManagerScreenHandler::SetAuthType( 255 const std::string& user_email, 256 ScreenlockBridge::LockHandler::AuthType auth_type, 257 const base::string16& auth_value) { 258 if (GetAuthType(user_email) == 259 ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD) 260 return; 261 262 user_auth_type_map_[user_email] = auth_type; 263 web_ui()->CallJavascriptFunction( 264 "login.AccountPickerScreen.setAuthType", 265 base::StringValue(user_email), 266 base::FundamentalValue(auth_type), 267 base::StringValue(auth_value)); 268 } 269 270 ScreenlockBridge::LockHandler::AuthType UserManagerScreenHandler::GetAuthType( 271 const std::string& user_email) const { 272 UserAuthTypeMap::const_iterator it = user_auth_type_map_.find(user_email); 273 if (it == user_auth_type_map_.end()) 274 return ScreenlockBridge::LockHandler::OFFLINE_PASSWORD; 275 return it->second; 276 } 277 278 void UserManagerScreenHandler::Unlock(const std::string& user_email) { 279 ProfileInfoCache& info_cache = 280 g_browser_process->profile_manager()->GetProfileInfoCache(); 281 const size_t profile_index = GetIndexOfProfileWithEmailAndName( 282 info_cache, base::UTF8ToUTF16(user_email), base::string16()); 283 DCHECK_LT(profile_index, info_cache.GetNumberOfProfiles()); 284 285 authenticating_profile_index_ = profile_index; 286 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL); 287 } 288 289 void UserManagerScreenHandler::AttemptEasySignin( 290 const std::string& user_email, 291 const std::string& secret, 292 const std::string& key_label) { 293 NOTREACHED(); 294 } 295 296 void UserManagerScreenHandler::HandleInitialize(const base::ListValue* args) { 297 // If the URL has a hash parameter, store it for later. 298 args->GetString(0, &url_hash_); 299 300 SendUserList(); 301 web_ui()->CallJavascriptFunction("cr.ui.Oobe.showUserManagerScreen", 302 base::FundamentalValue(IsGuestModeEnabled()), 303 base::FundamentalValue(IsAddPersonEnabled())); 304 desktop_type_ = chrome::GetHostDesktopTypeForNativeView( 305 web_ui()->GetWebContents()->GetNativeView()); 306 307 ScreenlockBridge::Get()->SetLockHandler(this); 308 } 309 310 void UserManagerScreenHandler::HandleAddUser(const base::ListValue* args) { 311 if (!IsAddPersonEnabled()) { 312 // The 'Add User' UI should not be showing. 313 NOTREACHED(); 314 return; 315 } 316 profiles::CreateAndSwitchToNewProfile( 317 desktop_type_, 318 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete, 319 weak_ptr_factory_.GetWeakPtr()), 320 ProfileMetrics::ADD_NEW_USER_MANAGER); 321 } 322 323 void UserManagerScreenHandler::HandleAuthenticatedLaunchUser( 324 const base::ListValue* args) { 325 base::string16 email_address; 326 if (!args->GetString(0, &email_address)) 327 return; 328 329 base::string16 display_name; 330 if (!args->GetString(1, &display_name)) 331 return; 332 333 std::string password; 334 if (!args->GetString(2, &password)) 335 return; 336 337 ProfileInfoCache& info_cache = 338 g_browser_process->profile_manager()->GetProfileInfoCache(); 339 size_t profile_index = GetIndexOfProfileWithEmailAndName( 340 info_cache, email_address, display_name); 341 if (profile_index >= info_cache.GetNumberOfProfiles()) { 342 NOTREACHED(); 343 return; 344 } 345 346 authenticating_profile_index_ = profile_index; 347 if (!chrome::ValidateLocalAuthCredentials(profile_index, password)) { 348 // Make a second attempt via an on-line authentication call. This handles 349 // profiles that are missing sign-in credentials and also cases where the 350 // password has been changed externally. 351 client_login_.reset(new GaiaAuthFetcher( 352 this, 353 GaiaConstants::kChromeSource, 354 web_ui()->GetWebContents()->GetBrowserContext()->GetRequestContext())); 355 std::string email_string; 356 args->GetString(0, &email_string); 357 client_login_->StartClientLogin( 358 email_string, 359 password, 360 GaiaConstants::kSyncService, 361 std::string(), 362 std::string(), 363 GaiaAuthFetcher::HostedAccountsAllowed); 364 password_attempt_ = password; 365 return; 366 } 367 368 ReportAuthenticationResult(true, ProfileMetrics::AUTH_LOCAL); 369 } 370 371 void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) { 372 DCHECK(args); 373 const base::Value* profile_path_value; 374 if (!args->Get(0, &profile_path_value)) 375 return; 376 377 base::FilePath profile_path; 378 if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) 379 return; 380 381 // This handler could have been called for a supervised user, for example 382 // because the user fiddled with the web inspector. Silently return in this 383 // case. 384 if (Profile::FromWebUI(web_ui())->IsSupervised()) 385 return; 386 387 if (!profiles::IsMultipleProfilesEnabled()) 388 return; 389 390 g_browser_process->profile_manager()->ScheduleProfileForDeletion( 391 profile_path, 392 base::Bind(&OpenNewWindowForProfile, desktop_type_)); 393 ProfileMetrics::LogProfileDeleteUser( 394 ProfileMetrics::DELETE_PROFILE_USER_MANAGER); 395 } 396 397 void UserManagerScreenHandler::HandleLaunchGuest(const base::ListValue* args) { 398 if (IsGuestModeEnabled()) { 399 ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_GUEST); 400 profiles::SwitchToGuestProfile( 401 desktop_type_, 402 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete, 403 weak_ptr_factory_.GetWeakPtr())); 404 } else { 405 // The UI should have prevented the user from allowing the selection of 406 // guest mode. 407 NOTREACHED(); 408 } 409 } 410 411 void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) { 412 base::string16 email_address; 413 base::string16 display_name; 414 415 if (!args->GetString(0, &email_address) || 416 !args->GetString(1, &display_name)) { 417 NOTREACHED(); 418 return; 419 } 420 421 ProfileInfoCache& info_cache = 422 g_browser_process->profile_manager()->GetProfileInfoCache(); 423 size_t profile_index = GetIndexOfProfileWithEmailAndName( 424 info_cache, email_address, display_name); 425 426 if (profile_index >= info_cache.GetNumberOfProfiles()) { 427 NOTREACHED(); 428 return; 429 } 430 431 // It's possible that a user breaks into the user-manager page using the 432 // JavaScript Inspector and causes a "locked" profile to call this 433 // unauthenticated version of "launch" instead of the proper one. Thus, 434 // we have to validate in (secure) C++ code that it really is a profile 435 // not needing authentication. If it is, just ignore the "launch" request. 436 if (info_cache.ProfileIsSigninRequiredAtIndex(profile_index)) 437 return; 438 ProfileMetrics::LogProfileAuthResult(ProfileMetrics::AUTH_UNNECESSARY); 439 440 base::FilePath path = info_cache.GetPathOfProfileAtIndex(profile_index); 441 profiles::SwitchToProfile( 442 path, 443 desktop_type_, 444 false, /* reuse any existing windows */ 445 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete, 446 weak_ptr_factory_.GetWeakPtr()), 447 ProfileMetrics::SWITCH_PROFILE_MANAGER); 448 } 449 450 void UserManagerScreenHandler::HandleAttemptUnlock( 451 const base::ListValue* args) { 452 std::string email; 453 CHECK(args->GetString(0, &email)); 454 GetScreenlockRouter(email)->OnAuthAttempted(GetAuthType(email), ""); 455 } 456 457 void UserManagerScreenHandler::HandleHardlockUserPod( 458 const base::ListValue* args) { 459 std::string email; 460 CHECK(args->GetString(0, &email)); 461 SetAuthType(email, 462 ScreenlockBridge::LockHandler::FORCE_OFFLINE_PASSWORD, 463 base::string16()); 464 HideUserPodCustomIcon(email); 465 } 466 467 void UserManagerScreenHandler::OnClientLoginSuccess( 468 const ClientLoginResult& result) { 469 chrome::SetLocalAuthCredentials(authenticating_profile_index_, 470 password_attempt_); 471 ReportAuthenticationResult(true, ProfileMetrics::AUTH_ONLINE); 472 } 473 474 void UserManagerScreenHandler::OnClientLoginFailure( 475 const GoogleServiceAuthError& error) { 476 const GoogleServiceAuthError::State state = error.state(); 477 // Some "error" results mean the password was correct but some other action 478 // should be taken. For our purposes, we only care that the password was 479 // correct so count those as a success. 480 bool success = (state == GoogleServiceAuthError::NONE || 481 state == GoogleServiceAuthError::CAPTCHA_REQUIRED || 482 state == GoogleServiceAuthError::TWO_FACTOR || 483 state == GoogleServiceAuthError::ACCOUNT_DELETED || 484 state == GoogleServiceAuthError::ACCOUNT_DISABLED); 485 bool offline = (state == GoogleServiceAuthError::CONNECTION_FAILED || 486 state == GoogleServiceAuthError::SERVICE_UNAVAILABLE || 487 state == GoogleServiceAuthError::REQUEST_CANCELED); 488 ProfileMetrics::ProfileAuth failure_metric = 489 offline ? ProfileMetrics::AUTH_FAILED_OFFLINE : 490 ProfileMetrics::AUTH_FAILED; 491 ReportAuthenticationResult( 492 success, success ? ProfileMetrics::AUTH_ONLINE : failure_metric); 493 } 494 495 void UserManagerScreenHandler::RegisterMessages() { 496 web_ui()->RegisterMessageCallback(kJsApiUserManagerInitialize, 497 base::Bind(&UserManagerScreenHandler::HandleInitialize, 498 base::Unretained(this))); 499 web_ui()->RegisterMessageCallback(kJsApiUserManagerAddUser, 500 base::Bind(&UserManagerScreenHandler::HandleAddUser, 501 base::Unretained(this))); 502 web_ui()->RegisterMessageCallback(kJsApiUserManagerAuthLaunchUser, 503 base::Bind(&UserManagerScreenHandler::HandleAuthenticatedLaunchUser, 504 base::Unretained(this))); 505 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchGuest, 506 base::Bind(&UserManagerScreenHandler::HandleLaunchGuest, 507 base::Unretained(this))); 508 web_ui()->RegisterMessageCallback(kJsApiUserManagerLaunchUser, 509 base::Bind(&UserManagerScreenHandler::HandleLaunchUser, 510 base::Unretained(this))); 511 web_ui()->RegisterMessageCallback(kJsApiUserManagerRemoveUser, 512 base::Bind(&UserManagerScreenHandler::HandleRemoveUser, 513 base::Unretained(this))); 514 web_ui()->RegisterMessageCallback(kJsApiUserManagerAttemptUnlock, 515 base::Bind(&UserManagerScreenHandler::HandleAttemptUnlock, 516 base::Unretained(this))); 517 518 const content::WebUI::MessageCallback& kDoNothingCallback = 519 base::Bind(&HandleAndDoNothing); 520 521 // Unused callbacks from screen_account_picker.js 522 web_ui()->RegisterMessageCallback("accountPickerReady", kDoNothingCallback); 523 web_ui()->RegisterMessageCallback("loginUIStateChanged", kDoNothingCallback); 524 web_ui()->RegisterMessageCallback("hideCaptivePortal", kDoNothingCallback); 525 web_ui()->RegisterMessageCallback("getTouchViewState", kDoNothingCallback); 526 // Unused callbacks from display_manager.js 527 web_ui()->RegisterMessageCallback("showAddUser", kDoNothingCallback); 528 web_ui()->RegisterMessageCallback("loadWallpaper", kDoNothingCallback); 529 web_ui()->RegisterMessageCallback("updateCurrentScreen", kDoNothingCallback); 530 web_ui()->RegisterMessageCallback("loginVisible", kDoNothingCallback); 531 // Unused callbacks from user_pod_row.js 532 web_ui()->RegisterMessageCallback("focusPod", kDoNothingCallback); 533 } 534 535 void UserManagerScreenHandler::GetLocalizedValues( 536 base::DictionaryValue* localized_strings) { 537 // For Control Bar. 538 localized_strings->SetString("signedIn", 539 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_ACTIVE_USER)); 540 localized_strings->SetString("signinButton", 541 l10n_util::GetStringUTF16(IDS_LOGIN_BUTTON)); 542 localized_strings->SetString("addUser", 543 l10n_util::GetStringUTF16(IDS_ADD_USER_BUTTON)); 544 localized_strings->SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL)); 545 localized_strings->SetString("browseAsGuest", 546 l10n_util::GetStringUTF16(IDS_GO_INCOGNITO_BUTTON)); 547 localized_strings->SetString("signOutUser", 548 l10n_util::GetStringUTF16(IDS_SCREEN_LOCK_SIGN_OUT)); 549 550 // For AccountPickerScreen. 551 localized_strings->SetString("screenType", "login-add-user"); 552 localized_strings->SetString("highlightStrength", "normal"); 553 localized_strings->SetString("title", 554 l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); 555 localized_strings->SetString("passwordHint", 556 l10n_util::GetStringUTF16(IDS_LOGIN_POD_EMPTY_PASSWORD_TEXT)); 557 localized_strings->SetString("signingIn", 558 l10n_util::GetStringUTF16(IDS_LOGIN_POD_SIGNING_IN)); 559 localized_strings->SetString("podMenuButtonAccessibleName", 560 l10n_util::GetStringUTF16(IDS_LOGIN_POD_MENU_BUTTON_ACCESSIBLE_NAME)); 561 localized_strings->SetString("podMenuRemoveItemAccessibleName", 562 l10n_util::GetStringUTF16( 563 IDS_LOGIN_POD_MENU_REMOVE_ITEM_ACCESSIBLE_NAME)); 564 localized_strings->SetString("removeUser", 565 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON)); 566 localized_strings->SetString("passwordFieldAccessibleName", 567 l10n_util::GetStringUTF16(IDS_LOGIN_POD_PASSWORD_FIELD_ACCESSIBLE_NAME)); 568 localized_strings->SetString("bootIntoWallpaper", "off"); 569 570 // For AccountPickerScreen, the remove user warning overlay. 571 localized_strings->SetString("removeUserWarningButtonTitle", 572 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING_BUTTON)); 573 localized_strings->SetString("removeUserWarningText", 574 l10n_util::GetStringUTF16(IDS_LOGIN_POD_USER_REMOVE_WARNING)); 575 localized_strings->SetString("removeSupervisedUserWarningText", 576 l10n_util::GetStringFUTF16( 577 IDS_LOGIN_POD_SUPERVISED_USER_REMOVE_WARNING, 578 base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL))); 579 580 // Strings needed for the User Manager tutorial slides. 581 localized_strings->SetString("tutorialNext", 582 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_NEXT)); 583 localized_strings->SetString("tutorialDone", 584 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_DONE)); 585 localized_strings->SetString("slideWelcomeTitle", 586 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TITLE)); 587 localized_strings->SetString("slideWelcomeText", 588 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_INTRO_TEXT)); 589 localized_strings->SetString("slideYourChromeTitle", 590 l10n_util::GetStringUTF16( 591 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TITLE)); 592 localized_strings->SetString("slideYourChromeText", l10n_util::GetStringUTF16( 593 IDS_USER_MANAGER_TUTORIAL_SLIDE_YOUR_CHROME_TEXT)); 594 localized_strings->SetString("slideGuestsTitle", 595 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TITLE)); 596 localized_strings->SetString("slideGuestsText", 597 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_GUEST_TEXT)); 598 localized_strings->SetString("slideFriendsTitle", 599 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TITLE)); 600 localized_strings->SetString("slideFriendsText", 601 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_FRIENDS_TEXT)); 602 localized_strings->SetString("slideCompleteTitle", 603 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TITLE)); 604 localized_strings->SetString("slideCompleteText", 605 l10n_util::GetStringUTF16(IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_TEXT)); 606 localized_strings->SetString("slideCompleteUserNotFound", 607 l10n_util::GetStringUTF16( 608 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_USER_NOT_FOUND)); 609 localized_strings->SetString("slideCompleteAddUser", 610 l10n_util::GetStringUTF16( 611 IDS_USER_MANAGER_TUTORIAL_SLIDE_OUTRO_ADD_USER)); 612 613 // Strings needed for the user_pod_template public account div, but not ever 614 // actually displayed for desktop users. 615 localized_strings->SetString("publicAccountReminder", base::string16()); 616 localized_strings->SetString("publicSessionLanguageAndInput", 617 base::string16()); 618 localized_strings->SetString("publicAccountEnter", base::string16()); 619 localized_strings->SetString("publicAccountEnterAccessibleName", 620 base::string16()); 621 localized_strings->SetString("publicSessionSelectLanguage", base::string16()); 622 localized_strings->SetString("publicSessionSelectKeyboard", base::string16()); 623 localized_strings->SetString("signinBannerText", base::string16()); 624 localized_strings->SetString("launchAppButton", base::string16()); 625 localized_strings->SetString("multiProfilesRestrictedPolicyTitle", 626 base::string16()); 627 localized_strings->SetString("multiProfilesNotAllowedPolicyMsg", 628 base::string16()); 629 localized_strings->SetString("multiProfilesPrimaryOnlyPolicyMsg", 630 base::string16()); 631 localized_strings->SetString("multiProfilesOwnerPrimaryOnlyMsg", 632 base::string16()); 633 } 634 635 void UserManagerScreenHandler::SendUserList() { 636 base::ListValue users_list; 637 base::FilePath active_profile_path = 638 web_ui()->GetWebContents()->GetBrowserContext()->GetPath(); 639 const ProfileInfoCache& info_cache = 640 g_browser_process->profile_manager()->GetProfileInfoCache(); 641 642 user_auth_type_map_.clear(); 643 644 // If the active user is a supervised user, then they may not perform 645 // certain actions (i.e. delete another user). 646 bool active_user_is_supervised = Profile::FromWebUI(web_ui())->IsSupervised(); 647 for (size_t i = 0; i < info_cache.GetNumberOfProfiles(); ++i) { 648 base::DictionaryValue* profile_value = new base::DictionaryValue(); 649 650 base::FilePath profile_path = info_cache.GetPathOfProfileAtIndex(i); 651 bool is_active_user = (profile_path == active_profile_path); 652 653 profile_value->SetString( 654 kKeyUsername, info_cache.GetUserNameOfProfileAtIndex(i)); 655 profile_value->SetString( 656 kKeyEmailAddress, info_cache.GetUserNameOfProfileAtIndex(i)); 657 // The profiles displayed in the User Manager are never guest profiles. 658 profile_value->SetString( 659 kKeyDisplayName, 660 profiles::GetAvatarNameForProfile(profile_path)); 661 profile_value->SetString(kKeyProfilePath, profile_path.MaybeAsASCII()); 662 profile_value->SetBoolean(kKeyPublicAccount, false); 663 profile_value->SetBoolean( 664 kKeySupervisedUser, info_cache.ProfileIsSupervisedAtIndex(i)); 665 profile_value->SetBoolean(kKeySignedIn, is_active_user); 666 profile_value->SetBoolean( 667 kKeyNeedsSignin, info_cache.ProfileIsSigninRequiredAtIndex(i)); 668 profile_value->SetBoolean(kKeyIsOwner, false); 669 profile_value->SetBoolean(kKeyCanRemove, !active_user_is_supervised); 670 profile_value->SetBoolean(kKeyIsDesktop, true); 671 profile_value->SetString( 672 kKeyAvatarUrl, GetAvatarImageAtIndex(i, info_cache)); 673 674 // The row of user pods should display the active user first. 675 if (is_active_user) 676 users_list.Insert(0, profile_value); 677 else 678 users_list.Append(profile_value); 679 } 680 681 web_ui()->CallJavascriptFunction("login.AccountPickerScreen.loadUsers", 682 users_list, base::FundamentalValue(IsGuestModeEnabled())); 683 } 684 685 void UserManagerScreenHandler::ReportAuthenticationResult( 686 bool success, 687 ProfileMetrics::ProfileAuth auth) { 688 ProfileMetrics::LogProfileAuthResult(auth); 689 password_attempt_.clear(); 690 691 if (success) { 692 ProfileInfoCache& info_cache = 693 g_browser_process->profile_manager()->GetProfileInfoCache(); 694 info_cache.SetProfileSigninRequiredAtIndex( 695 authenticating_profile_index_, false); 696 base::FilePath path = info_cache.GetPathOfProfileAtIndex( 697 authenticating_profile_index_); 698 profiles::SwitchToProfile( 699 path, 700 desktop_type_, 701 true, 702 base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete, 703 weak_ptr_factory_.GetWeakPtr()), 704 ProfileMetrics::SWITCH_PROFILE_UNLOCK); 705 } else { 706 web_ui()->CallJavascriptFunction( 707 "cr.ui.Oobe.showSignInError", 708 base::FundamentalValue(0), 709 base::StringValue(l10n_util::GetStringUTF8( 710 auth == ProfileMetrics::AUTH_FAILED_OFFLINE ? 711 IDS_LOGIN_ERROR_AUTHENTICATING_OFFLINE : 712 IDS_LOGIN_ERROR_AUTHENTICATING)), 713 base::StringValue(""), 714 base::FundamentalValue(0)); 715 } 716 } 717 718 void UserManagerScreenHandler::OnBrowserWindowReady(Browser* browser) { 719 DCHECK(browser); 720 DCHECK(browser->window()); 721 if (url_hash_ == profiles::kUserManagerSelectProfileTaskManager) { 722 base::MessageLoop::current()->PostTask( 723 FROM_HERE, base::Bind(&chrome::ShowTaskManager, browser)); 724 } else if (url_hash_ == profiles::kUserManagerSelectProfileAboutChrome) { 725 base::MessageLoop::current()->PostTask( 726 FROM_HERE, base::Bind(&chrome::ShowAboutChrome, browser)); 727 } 728 729 // This call is last as it deletes this object. 730 UserManager::Hide(); 731 } 732 733 void UserManagerScreenHandler::Observe( 734 int type, 735 const content::NotificationSource& source, 736 const content::NotificationDetails& details) { 737 switch (type) { 738 case chrome::NOTIFICATION_BROWSER_WINDOW_READY: 739 // Only respond to one Browser Window Ready event. 740 registrar_.Remove(this, 741 chrome::NOTIFICATION_BROWSER_WINDOW_READY, 742 content::NotificationService::AllSources()); 743 OnBrowserWindowReady(content::Source<Browser>(source).ptr()); 744 break; 745 default: 746 NOTREACHED(); 747 } 748 } 749 750 // This callback is run after switching to a new profile has finished. This 751 // means either a new browser has been created (but not the window), or an 752 // existing one has been found. The HideUserManager task needs to be posted 753 // since closing the User Manager before the window is created can flakily 754 // cause Chrome to close. 755 void UserManagerScreenHandler::OnSwitchToProfileComplete( 756 Profile* profile, Profile::CreateStatus profile_create_status) { 757 Browser* browser = chrome::FindAnyBrowser(profile, false, desktop_type_); 758 if (browser && browser->window()) { 759 OnBrowserWindowReady(browser); 760 } else { 761 registrar_.Add(this, 762 chrome::NOTIFICATION_BROWSER_WINDOW_READY, 763 content::NotificationService::AllSources()); 764 } 765 } 766