supervised_user_creation_screen.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
1// Copyright 2014 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/chromeos/login/supervised/supervised_user_creation_screen.h" 6 7#include "ash/desktop_background/desktop_background_controller.h" 8#include "ash/shell.h" 9#include "base/rand_util.h" 10#include "base/values.h" 11#include "chrome/browser/chromeos/camera_detector.h" 12#include "chrome/browser/chromeos/login/existing_user_controller.h" 13#include "chrome/browser/chromeos/login/screens/error_screen.h" 14#include "chrome/browser/chromeos/login/screens/screen_observer.h" 15#include "chrome/browser/chromeos/login/signin_specifics.h" 16#include "chrome/browser/chromeos/login/supervised/supervised_user_authentication.h" 17#include "chrome/browser/chromeos/login/supervised/supervised_user_creation_controller.h" 18#include "chrome/browser/chromeos/login/supervised/supervised_user_creation_controller_new.h" 19#include "chrome/browser/chromeos/login/users/avatar/user_image_manager.h" 20#include "chrome/browser/chromeos/login/users/chrome_user_manager.h" 21#include "chrome/browser/chromeos/login/users/supervised_user_manager.h" 22#include "chrome/browser/chromeos/login/wizard_controller.h" 23#include "chrome/browser/supervised_user/supervised_user_constants.h" 24#include "chrome/browser/supervised_user/supervised_user_shared_settings_service.h" 25#include "chrome/browser/supervised_user/supervised_user_shared_settings_service_factory.h" 26#include "chrome/browser/supervised_user/supervised_user_sync_service.h" 27#include "chrome/browser/supervised_user/supervised_user_sync_service_factory.h" 28#include "chrome/grit/generated_resources.h" 29#include "chromeos/login/auth/key.h" 30#include "chromeos/login/auth/user_context.h" 31#include "chromeos/network/network_state.h" 32#include "components/user_manager/user.h" 33#include "components/user_manager/user_image/user_image.h" 34#include "content/public/browser/browser_thread.h" 35#include "third_party/skia/include/core/SkBitmap.h" 36#include "ui/base/l10n/l10n_util.h" 37#include "ui/gfx/image/image_skia.h" 38 39namespace chromeos { 40 41namespace { 42 43// Key for (boolean) value that indicates that user already exists on device. 44const char kUserExists[] = "exists"; 45// Key for value that indicates why user can not be imported. 46const char kUserConflict[] = "conflict"; 47// User is already imported. 48const char kUserConflictImported[] = "imported"; 49// There is another supervised user with same name. 50const char kUserConflictName[] = "name"; 51 52const char kUserNeedPassword[] = "needPassword"; 53 54const char kAvatarURLKey[] = "avatarurl"; 55const char kRandomAvatarKey[] = "randomAvatar"; 56const char kNameOfIntroScreen[] = "intro"; 57const char kNameOfNewUserParametersScreen[] = "username"; 58 59void ConfigureErrorScreen(ErrorScreen* screen, 60 const NetworkState* network, 61 const NetworkPortalDetector::CaptivePortalStatus status) { 62 switch (status) { 63 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN: 64 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE: 65 NOTREACHED(); 66 break; 67 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE: 68 screen->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE, 69 std::string()); 70 break; 71 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL: 72 screen->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL, 73 network ? network->name() : std::string()); 74 screen->FixCaptivePortal(); 75 break; 76 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED: 77 screen->SetErrorState(ErrorScreen::ERROR_STATE_PROXY, 78 std::string()); 79 break; 80 default: 81 NOTREACHED(); 82 break; 83 } 84} 85 86} // namespace 87 88SupervisedUserCreationScreen::SupervisedUserCreationScreen( 89 ScreenObserver* observer, 90 SupervisedUserCreationScreenHandler* actor) 91 : WizardScreen(observer), 92 weak_factory_(this), 93 actor_(actor), 94 on_error_screen_(false), 95 last_page_(kNameOfIntroScreen), 96 sync_service_(NULL), 97 image_decoder_(NULL), 98 apply_photo_after_decoding_(false), 99 selected_image_(0) { 100 DCHECK(actor_); 101 if (actor_) 102 actor_->SetDelegate(this); 103} 104 105SupervisedUserCreationScreen::~SupervisedUserCreationScreen() { 106 CameraPresenceNotifier::GetInstance()->RemoveObserver(this); 107 if (sync_service_) 108 sync_service_->RemoveObserver(this); 109 if (actor_) 110 actor_->SetDelegate(NULL); 111 if (image_decoder_.get()) 112 image_decoder_->set_delegate(NULL); 113 NetworkPortalDetector::Get()->RemoveObserver(this); 114} 115 116void SupervisedUserCreationScreen::PrepareToShow() { 117 if (actor_) 118 actor_->PrepareToShow(); 119} 120 121void SupervisedUserCreationScreen::Show() { 122 CameraPresenceNotifier::GetInstance()->AddObserver(this); 123 if (actor_) { 124 actor_->Show(); 125 // TODO(antrim) : temorary hack (until upcoming hackaton). Should be 126 // removed once we have screens reworked. 127 if (on_error_screen_) 128 actor_->ShowPage(last_page_); 129 else 130 actor_->ShowIntroPage(); 131 } 132 133 if (!on_error_screen_) 134 NetworkPortalDetector::Get()->AddAndFireObserver(this); 135 on_error_screen_ = false; 136} 137 138void SupervisedUserCreationScreen::OnPageSelected(const std::string& page) { 139 last_page_ = page; 140} 141 142void SupervisedUserCreationScreen::OnPortalDetectionCompleted( 143 const NetworkState* network, 144 const NetworkPortalDetector::CaptivePortalState& state) { 145 if (state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) { 146 get_screen_observer()->HideErrorScreen(this); 147 } else { 148 on_error_screen_ = true; 149 ErrorScreen* screen = get_screen_observer()->GetErrorScreen(); 150 ConfigureErrorScreen(screen, network, state.status); 151 screen->SetUIState(ErrorScreen::UI_STATE_SUPERVISED); 152 get_screen_observer()->ShowErrorScreen(); 153 } 154} 155 156void SupervisedUserCreationScreen::ShowManagerInconsistentStateErrorScreen() { 157 if (!actor_) 158 return; 159 actor_->ShowErrorPage( 160 l10n_util::GetStringUTF16( 161 IDS_CREATE_SUPERVISED_USER_MANAGER_INCONSISTENT_STATE_TITLE), 162 l10n_util::GetStringUTF16( 163 IDS_CREATE_SUPERVISED_USER_MANAGER_INCONSISTENT_STATE), 164 l10n_util::GetStringUTF16( 165 IDS_CREATE_SUPERVISED_USER_MANAGER_INCONSISTENT_STATE_BUTTON)); 166} 167 168void SupervisedUserCreationScreen::ShowInitialScreen() { 169 if (actor_) 170 actor_->ShowIntroPage(); 171} 172 173void SupervisedUserCreationScreen::Hide() { 174 CameraPresenceNotifier::GetInstance()->RemoveObserver(this); 175 if (actor_) 176 actor_->Hide(); 177 if (!on_error_screen_) 178 NetworkPortalDetector::Get()->RemoveObserver(this); 179} 180 181std::string SupervisedUserCreationScreen::GetName() const { 182 return WizardController::kSupervisedUserCreationScreenName; 183} 184 185void SupervisedUserCreationScreen::AbortFlow() { 186 controller_->CancelCreation(); 187} 188 189void SupervisedUserCreationScreen::FinishFlow() { 190 controller_->FinishCreation(); 191} 192 193void SupervisedUserCreationScreen::AuthenticateManager( 194 const std::string& manager_id, 195 const std::string& manager_password) { 196 // Make sure no two controllers exist at the same time. 197 controller_.reset(); 198 199 controller_.reset(new SupervisedUserCreationControllerNew(this, manager_id)); 200 201 UserContext user_context(manager_id); 202 user_context.SetKey(Key(manager_password)); 203 ExistingUserController::current_controller()->Login(user_context, 204 SigninSpecifics()); 205} 206 207void SupervisedUserCreationScreen::CreateSupervisedUser( 208 const base::string16& display_name, 209 const std::string& supervised_user_password) { 210 DCHECK(controller_.get()); 211 int image; 212 if (selected_image_ == user_manager::User::USER_IMAGE_EXTERNAL) 213 // TODO(dzhioev): crbug/249660 214 image = SupervisedUserCreationController::kDummyAvatarIndex; 215 else 216 image = selected_image_; 217 controller_->StartCreation(display_name, supervised_user_password, image); 218} 219 220void SupervisedUserCreationScreen::ImportSupervisedUser( 221 const std::string& user_id) { 222 DCHECK(controller_.get()); 223 DCHECK(existing_users_.get()); 224 VLOG(1) << "Importing user " << user_id; 225 base::DictionaryValue* user_info; 226 if (!existing_users_->GetDictionary(user_id, &user_info)) { 227 LOG(ERROR) << "Can not import non-existing user " << user_id; 228 return; 229 } 230 base::string16 display_name; 231 std::string master_key; 232 std::string signature_key; 233 std::string encryption_key; 234 std::string avatar; 235 bool exists; 236 int avatar_index = SupervisedUserCreationController::kDummyAvatarIndex; 237 user_info->GetString(SupervisedUserSyncService::kName, &display_name); 238 user_info->GetString(SupervisedUserSyncService::kMasterKey, &master_key); 239 user_info->GetString(SupervisedUserSyncService::kPasswordSignatureKey, 240 &signature_key); 241 user_info->GetString(SupervisedUserSyncService::kPasswordEncryptionKey, 242 &encryption_key); 243 user_info->GetString(SupervisedUserSyncService::kChromeOsAvatar, &avatar); 244 user_info->GetBoolean(kUserExists, &exists); 245 246 // We should not get here with existing user selected, so just display error. 247 if (exists) { 248 actor_->ShowErrorPage( 249 l10n_util::GetStringUTF16( 250 IDS_CREATE_SUPERVISED_USER_GENERIC_ERROR_TITLE), 251 l10n_util::GetStringUTF16( 252 IDS_CREATE_SUPERVISED_USER_GENERIC_ERROR), 253 l10n_util::GetStringUTF16( 254 IDS_CREATE_SUPERVISED_USER_GENERIC_ERROR_BUTTON)); 255 return; 256 } 257 258 SupervisedUserSyncService::GetAvatarIndex(avatar, &avatar_index); 259 260 const base::DictionaryValue* password_data = NULL; 261 SupervisedUserSharedSettingsService* shared_settings_service = 262 SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext( 263 controller_->GetManagerProfile()); 264 const base::Value* value = shared_settings_service->GetValue( 265 user_id, supervised_users::kChromeOSPasswordData); 266 267 bool password_right_here = value && value->GetAsDictionary(&password_data) && 268 !password_data->empty(); 269 270 if (password_right_here) { 271 controller_->StartImport(display_name, 272 avatar_index, 273 user_id, 274 master_key, 275 password_data, 276 encryption_key, 277 signature_key); 278 } else { 279 NOTREACHED() << " Oops, no password"; 280 } 281} 282 283// TODO(antrim): Code duplication with previous method will be removed once 284// password sync is implemented. 285void SupervisedUserCreationScreen::ImportSupervisedUserWithPassword( 286 const std::string& user_id, 287 const std::string& password) { 288 DCHECK(controller_.get()); 289 DCHECK(existing_users_.get()); 290 VLOG(1) << "Importing user " << user_id; 291 base::DictionaryValue* user_info; 292 if (!existing_users_->GetDictionary(user_id, &user_info)) { 293 LOG(ERROR) << "Can not import non-existing user " << user_id; 294 return; 295 } 296 base::string16 display_name; 297 std::string master_key; 298 std::string avatar; 299 bool exists; 300 int avatar_index = SupervisedUserCreationController::kDummyAvatarIndex; 301 user_info->GetString(SupervisedUserSyncService::kName, &display_name); 302 user_info->GetString(SupervisedUserSyncService::kMasterKey, &master_key); 303 user_info->GetString(SupervisedUserSyncService::kChromeOsAvatar, &avatar); 304 user_info->GetBoolean(kUserExists, &exists); 305 306 // We should not get here with existing user selected, so just display error. 307 if (exists) { 308 actor_->ShowErrorPage( 309 l10n_util::GetStringUTF16( 310 IDS_CREATE_SUPERVISED_USER_GENERIC_ERROR_TITLE), 311 l10n_util::GetStringUTF16( 312 IDS_CREATE_SUPERVISED_USER_GENERIC_ERROR), 313 l10n_util::GetStringUTF16( 314 IDS_CREATE_SUPERVISED_USER_GENERIC_ERROR_BUTTON)); 315 return; 316 } 317 318 SupervisedUserSyncService::GetAvatarIndex(avatar, &avatar_index); 319 320 controller_->StartImport(display_name, 321 password, 322 avatar_index, 323 user_id, 324 master_key); 325} 326 327void SupervisedUserCreationScreen::OnManagerLoginFailure() { 328 if (actor_) 329 actor_->ShowManagerPasswordError(); 330} 331 332void SupervisedUserCreationScreen::OnManagerFullyAuthenticated( 333 Profile* manager_profile) { 334 DCHECK(controller_.get()); 335 // For manager user, move desktop to locked container so that windows created 336 // during the user image picker step are below it. 337 ash::Shell::GetInstance()-> 338 desktop_background_controller()->MoveDesktopToLockedContainer(); 339 340 controller_->SetManagerProfile(manager_profile); 341 if (actor_) 342 actor_->ShowUsernamePage(); 343 344 last_page_ = kNameOfNewUserParametersScreen; 345 CHECK(!sync_service_); 346 sync_service_ = SupervisedUserSyncServiceFactory::GetForProfile( 347 manager_profile); 348 sync_service_->AddObserver(this); 349 OnSupervisedUsersChanged(); 350} 351 352void SupervisedUserCreationScreen::OnSupervisedUsersChanged() { 353 CHECK(sync_service_); 354 sync_service_->GetSupervisedUsersAsync( 355 base::Bind(&SupervisedUserCreationScreen::OnGetSupervisedUsers, 356 weak_factory_.GetWeakPtr())); 357} 358 359void SupervisedUserCreationScreen::OnManagerCryptohomeAuthenticated() { 360 if (actor_) { 361 actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16( 362 IDS_CREATE_SUPERVISED_USER_CREATION_AUTH_PROGRESS_MESSAGE)); 363 } 364} 365 366void SupervisedUserCreationScreen::OnActorDestroyed( 367 SupervisedUserCreationScreenHandler* actor) { 368 if (actor_ == actor) 369 actor_ = NULL; 370} 371 372void SupervisedUserCreationScreen::OnCreationError( 373 SupervisedUserCreationController::ErrorCode code) { 374 LOG(ERROR) << "Supervised user creation failure, code: " << code; 375 376 base::string16 title; 377 base::string16 message; 378 base::string16 button; 379 // TODO(antrim) : find out which errors do we really have. 380 // We might reuse some error messages from ordinary user flow. 381 switch (code) { 382 case SupervisedUserCreationController::CRYPTOHOME_NO_MOUNT: 383 case SupervisedUserCreationController::CRYPTOHOME_FAILED_MOUNT: 384 case SupervisedUserCreationController::CRYPTOHOME_FAILED_TPM: 385 title = l10n_util::GetStringUTF16( 386 IDS_CREATE_SUPERVISED_USER_TPM_ERROR_TITLE); 387 message = l10n_util::GetStringUTF16( 388 IDS_CREATE_SUPERVISED_USER_TPM_ERROR); 389 button = l10n_util::GetStringUTF16( 390 IDS_CREATE_SUPERVISED_USER_TPM_ERROR_BUTTON); 391 break; 392 case SupervisedUserCreationController::CLOUD_SERVER_ERROR: 393 case SupervisedUserCreationController::TOKEN_WRITE_FAILED: 394 title = l10n_util::GetStringUTF16( 395 IDS_CREATE_SUPERVISED_USER_GENERIC_ERROR_TITLE); 396 message = l10n_util::GetStringUTF16( 397 IDS_CREATE_SUPERVISED_USER_GENERIC_ERROR); 398 button = l10n_util::GetStringUTF16( 399 IDS_CREATE_SUPERVISED_USER_GENERIC_ERROR_BUTTON); 400 break; 401 case SupervisedUserCreationController::NO_ERROR: 402 NOTREACHED(); 403 } 404 if (actor_) 405 actor_->ShowErrorPage(title, message, button); 406} 407 408void SupervisedUserCreationScreen::OnCreationTimeout() { 409 if (actor_) { 410 actor_->ShowStatusMessage(false /* error */, l10n_util::GetStringUTF16( 411 IDS_CREATE_SUPERVISED_USER_CREATION_CREATION_TIMEOUT_MESSAGE)); 412 } 413} 414 415void SupervisedUserCreationScreen::OnLongCreationWarning() { 416 if (actor_) { 417 actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16( 418 IDS_PROFILES_CREATE_SUPERVISED_JUST_SIGNED_IN)); 419 } 420} 421 422bool SupervisedUserCreationScreen::FindUserByDisplayName( 423 const base::string16& display_name, 424 std::string *out_id) const { 425 if (!existing_users_.get()) 426 return false; 427 for (base::DictionaryValue::Iterator it(*existing_users_.get()); 428 !it.IsAtEnd(); it.Advance()) { 429 const base::DictionaryValue* user_info = 430 static_cast<const base::DictionaryValue*>(&it.value()); 431 base::string16 user_display_name; 432 if (user_info->GetString(SupervisedUserSyncService::kName, 433 &user_display_name)) { 434 if (display_name == user_display_name) { 435 if (out_id) 436 *out_id = it.key(); 437 return true; 438 } 439 } 440 } 441 return false; 442} 443 444// TODO(antrim) : this is an explicit code duplications with UserImageScreen. 445// It should be removed by issue 251179. 446 447void SupervisedUserCreationScreen::ApplyPicture() { 448 std::string user_id = controller_->GetSupervisedUserId(); 449 UserImageManager* image_manager = 450 ChromeUserManager::Get()->GetUserImageManager(user_id); 451 switch (selected_image_) { 452 case user_manager::User::USER_IMAGE_EXTERNAL: 453 // Photo decoding may not have been finished yet. 454 if (user_photo_.isNull()) { 455 apply_photo_after_decoding_ = true; 456 return; 457 } 458 image_manager->SaveUserImage( 459 user_manager::UserImage::CreateAndEncode(user_photo_)); 460 break; 461 case user_manager::User::USER_IMAGE_PROFILE: 462 NOTREACHED() << "Supervised users have no profile pictures"; 463 break; 464 default: 465 DCHECK(selected_image_ >= 0 && 466 selected_image_ < user_manager::kDefaultImagesCount); 467 image_manager->SaveUserDefaultImageIndex(selected_image_); 468 break; 469 } 470 // Proceed to tutorial. 471 actor_->ShowTutorialPage(); 472} 473 474void SupervisedUserCreationScreen::OnCreationSuccess() { 475 ApplyPicture(); 476} 477 478void SupervisedUserCreationScreen::OnCameraPresenceCheckDone( 479 bool is_camera_present) { 480 if (actor_) 481 actor_->SetCameraPresent(is_camera_present); 482} 483 484void SupervisedUserCreationScreen::OnGetSupervisedUsers( 485 const base::DictionaryValue* users) { 486 // Copy for passing to WebUI, contains only id, name and avatar URL. 487 scoped_ptr<base::ListValue> ui_users(new base::ListValue()); 488 SupervisedUserManager* supervised_user_manager = 489 ChromeUserManager::Get()->GetSupervisedUserManager(); 490 491 // Stored copy, contains all necessary information. 492 existing_users_.reset(new base::DictionaryValue()); 493 for (base::DictionaryValue::Iterator it(*users); !it.IsAtEnd(); 494 it.Advance()) { 495 // Copy that would be stored in this class. 496 base::DictionaryValue* local_copy = 497 static_cast<base::DictionaryValue*>(it.value().DeepCopy()); 498 // Copy that would be passed to WebUI. It has some extra values for 499 // displaying, but does not contain sensitive data, such as master password. 500 base::DictionaryValue* ui_copy = 501 static_cast<base::DictionaryValue*>(new base::DictionaryValue()); 502 503 int avatar_index = SupervisedUserCreationController::kDummyAvatarIndex; 504 std::string chromeos_avatar; 505 if (local_copy->GetString(SupervisedUserSyncService::kChromeOsAvatar, 506 &chromeos_avatar) && 507 !chromeos_avatar.empty() && 508 SupervisedUserSyncService::GetAvatarIndex( 509 chromeos_avatar, &avatar_index)) { 510 ui_copy->SetString(kAvatarURLKey, 511 user_manager::GetDefaultImageUrl(avatar_index)); 512 } else { 513 int i = base::RandInt(user_manager::kFirstDefaultImageIndex, 514 user_manager::kDefaultImagesCount - 1); 515 local_copy->SetString( 516 SupervisedUserSyncService::kChromeOsAvatar, 517 SupervisedUserSyncService::BuildAvatarString(i)); 518 local_copy->SetBoolean(kRandomAvatarKey, true); 519 ui_copy->SetString(kAvatarURLKey, user_manager::GetDefaultImageUrl(i)); 520 } 521 522 local_copy->SetBoolean(kUserExists, false); 523 ui_copy->SetBoolean(kUserExists, false); 524 525 base::string16 display_name; 526 local_copy->GetString(SupervisedUserSyncService::kName, &display_name); 527 528 if (supervised_user_manager->FindBySyncId(it.key())) { 529 local_copy->SetBoolean(kUserExists, true); 530 ui_copy->SetBoolean(kUserExists, true); 531 local_copy->SetString(kUserConflict, kUserConflictImported); 532 ui_copy->SetString(kUserConflict, kUserConflictImported); 533 } else if (supervised_user_manager->FindByDisplayName(display_name)) { 534 local_copy->SetBoolean(kUserExists, true); 535 ui_copy->SetBoolean(kUserExists, true); 536 local_copy->SetString(kUserConflict, kUserConflictName); 537 ui_copy->SetString(kUserConflict, kUserConflictName); 538 } 539 ui_copy->SetString(SupervisedUserSyncService::kName, display_name); 540 541 std::string signature_key; 542 bool has_password = 543 local_copy->GetString(SupervisedUserSyncService::kPasswordSignatureKey, 544 &signature_key) && 545 !signature_key.empty(); 546 547 ui_copy->SetBoolean(kUserNeedPassword, !has_password); 548 ui_copy->SetString("id", it.key()); 549 550 existing_users_->Set(it.key(), local_copy); 551 ui_users->Append(ui_copy); 552 } 553 actor_->ShowExistingSupervisedUsers(ui_users.get()); 554} 555 556void SupervisedUserCreationScreen::OnPhotoTaken( 557 const std::string& raw_data) { 558 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); 559 user_photo_ = gfx::ImageSkia(); 560 if (image_decoder_.get()) 561 image_decoder_->set_delegate(NULL); 562 image_decoder_ = new ImageDecoder(this, raw_data, 563 ImageDecoder::DEFAULT_CODEC); 564 scoped_refptr<base::MessageLoopProxy> task_runner = 565 content::BrowserThread::GetMessageLoopProxyForThread( 566 content::BrowserThread::UI); 567 image_decoder_->Start(task_runner); 568} 569 570void SupervisedUserCreationScreen::OnImageDecoded( 571 const ImageDecoder* decoder, 572 const SkBitmap& decoded_image) { 573 DCHECK_EQ(image_decoder_.get(), decoder); 574 user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image); 575 if (apply_photo_after_decoding_) 576 ApplyPicture(); 577} 578 579void SupervisedUserCreationScreen::OnDecodeImageFailed( 580 const ImageDecoder* decoder) { 581 NOTREACHED() << "Failed to decode PNG image from WebUI"; 582} 583 584void SupervisedUserCreationScreen::OnImageSelected( 585 const std::string& image_type, 586 const std::string& image_url) { 587 if (image_url.empty()) 588 return; 589 int user_image_index = user_manager::User::USER_IMAGE_INVALID; 590 if (image_type == "default" && 591 user_manager::IsDefaultImageUrl(image_url, &user_image_index)) { 592 selected_image_ = user_image_index; 593 } else if (image_type == "camera") { 594 selected_image_ = user_manager::User::USER_IMAGE_EXTERNAL; 595 } else { 596 NOTREACHED() << "Unexpected image type: " << image_type; 597 } 598} 599 600void SupervisedUserCreationScreen::OnImageAccepted() { 601} 602 603} // namespace chromeos 604