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