1 // Copyright (c) 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.
5 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h"
7 #include "ash/desktop_background/desktop_background_controller.h"
9 #include "base/command_line.h"
10 #include "base/rand_util.h"
11 #include "base/values.h"
12 #include "chrome/browser/chromeos/camera_detector.h"
13 #include "chrome/browser/chromeos/login/existing_user_controller.h"
14 #include "chrome/browser/chromeos/login/managed/managed_user_creation_controller.h"
15 #include "chrome/browser/chromeos/login/managed/managed_user_creation_controller_new.h"
16 #include "chrome/browser/chromeos/login/managed/managed_user_creation_controller_old.h"
17 #include "chrome/browser/chromeos/login/managed/supervised_user_authentication.h"
18 #include "chrome/browser/chromeos/login/screens/error_screen.h"
19 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
20 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
21 #include "chrome/browser/chromeos/login/user_image.h"
22 #include "chrome/browser/chromeos/login/user_image_manager.h"
23 #include "chrome/browser/chromeos/login/wizard_controller.h"
24 #include "chrome/browser/managed_mode/managed_user_sync_service.h"
25 #include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chromeos/network/network_state.h"
28 #include "content/public/browser/browser_thread.h"
29 #include "grit/generated_resources.h"
30 #include "third_party/skia/include/core/SkBitmap.h"
31 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/gfx/image/image_skia.h"
38 // Key for (boolean) value that indicates that user already exists on device.
39 const char kUserExists[] = "exists";
40 // Key for value that indicates why user can not be imported.
41 const char kUserConflict[] = "conflict";
42 // User is already imported.
43 const char kUserConflictImported[] = "imported";
44 // There is another supervised user with same name.
45 const char kUserConflictName[] = "name";
47 const char kUserNeedPassword[] = "needPassword";
49 const char kAvatarURLKey[] = "avatarurl";
50 const char kRandomAvatarKey[] = "randomAvatar";
51 const char kNameOfIntroScreen[] = "intro";
52 const char kNameOfNewUserParametersScreen[] = "username";
54 void ConfigureErrorScreen(ErrorScreen* screen,
55 const NetworkState* network,
56 const NetworkPortalDetector::CaptivePortalStatus status) {
58 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
59 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
62 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
63 screen->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
66 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
67 screen->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
68 network ? network->name() : std::string());
69 screen->FixCaptivePortal();
71 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
72 screen->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
83 LocallyManagedUserCreationScreen::LocallyManagedUserCreationScreen(
84 ScreenObserver* observer,
85 LocallyManagedUserCreationScreenHandler* actor)
86 : WizardScreen(observer),
89 on_error_screen_(false),
90 last_page_(kNameOfIntroScreen),
92 apply_photo_after_decoding_(false),
96 actor_->SetDelegate(this);
99 LocallyManagedUserCreationScreen::~LocallyManagedUserCreationScreen() {
100 CameraPresenceNotifier::GetInstance()->RemoveObserver(this);
102 actor_->SetDelegate(NULL);
103 if (image_decoder_.get())
104 image_decoder_->set_delegate(NULL);
105 NetworkPortalDetector::Get()->RemoveObserver(this);
108 void LocallyManagedUserCreationScreen::PrepareToShow() {
110 actor_->PrepareToShow();
113 void LocallyManagedUserCreationScreen::Show() {
114 CameraPresenceNotifier::GetInstance()->AddObserver(this);
117 // TODO(antrim) : temorary hack (until upcoming hackaton). Should be
118 // removed once we have screens reworked.
119 if (on_error_screen_)
120 actor_->ShowPage(last_page_);
122 actor_->ShowIntroPage();
125 if (!on_error_screen_)
126 NetworkPortalDetector::Get()->AddAndFireObserver(this);
127 on_error_screen_ = false;
130 void LocallyManagedUserCreationScreen::OnPageSelected(const std::string& page) {
134 void LocallyManagedUserCreationScreen::OnPortalDetectionCompleted(
135 const NetworkState* network,
136 const NetworkPortalDetector::CaptivePortalState& state) {
137 if (state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) {
138 get_screen_observer()->HideErrorScreen(this);
140 on_error_screen_ = true;
141 ErrorScreen* screen = get_screen_observer()->GetErrorScreen();
142 ConfigureErrorScreen(screen, network, state.status);
143 screen->SetUIState(ErrorScreen::UI_STATE_LOCALLY_MANAGED);
144 get_screen_observer()->ShowErrorScreen();
148 void LocallyManagedUserCreationScreen::
149 ShowManagerInconsistentStateErrorScreen() {
152 actor_->ShowErrorPage(
153 l10n_util::GetStringUTF16(
154 IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_TITLE),
155 l10n_util::GetStringUTF16(
156 IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE),
157 l10n_util::GetStringUTF16(
158 IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_BUTTON));
161 void LocallyManagedUserCreationScreen::ShowInitialScreen() {
163 actor_->ShowIntroPage();
166 void LocallyManagedUserCreationScreen::Hide() {
167 CameraPresenceNotifier::GetInstance()->RemoveObserver(this);
170 if (!on_error_screen_)
171 NetworkPortalDetector::Get()->RemoveObserver(this);
174 std::string LocallyManagedUserCreationScreen::GetName() const {
175 return WizardController::kLocallyManagedUserCreationScreenName;
178 void LocallyManagedUserCreationScreen::AbortFlow() {
179 controller_->CancelCreation();
182 void LocallyManagedUserCreationScreen::FinishFlow() {
183 controller_->FinishCreation();
186 void LocallyManagedUserCreationScreen::AuthenticateManager(
187 const std::string& manager_id,
188 const std::string& manager_password) {
189 // Make sure no two controllers exist at the same time.
191 SupervisedUserAuthentication* authentication =
192 UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
194 if (authentication->GetStableSchema() ==
195 SupervisedUserAuthentication::SCHEMA_PLAIN) {
196 controller_.reset(new ManagedUserCreationControllerOld(this, manager_id));
198 controller_.reset(new ManagedUserCreationControllerNew(this, manager_id));
201 ExistingUserController::current_controller()->
202 Login(UserContext(manager_id,
204 std::string() /* auth_code */));
207 void LocallyManagedUserCreationScreen::CreateManagedUser(
208 const base::string16& display_name,
209 const std::string& managed_user_password) {
210 DCHECK(controller_.get());
212 if (selected_image_ == User::kExternalImageIndex)
213 // TODO(dzhioev): crbug/249660
214 image = ManagedUserCreationController::kDummyAvatarIndex;
216 image = selected_image_;
217 controller_->StartCreation(display_name, managed_user_password, image);
220 void LocallyManagedUserCreationScreen::ImportManagedUser(
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;
230 base::string16 display_name;
231 std::string master_key;
234 int avatar_index = ManagedUserCreationController::kDummyAvatarIndex;
235 user_info->GetString(ManagedUserSyncService::kName, &display_name);
236 user_info->GetString(ManagedUserSyncService::kMasterKey, &master_key);
237 user_info->GetString(ManagedUserSyncService::kChromeOsAvatar, &avatar);
238 user_info->GetBoolean(kUserExists, &exists);
240 // We should not get here with existing user selected, so just display error.
242 actor_->ShowErrorPage(
243 l10n_util::GetStringUTF16(
244 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE),
245 l10n_util::GetStringUTF16(
246 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR),
247 l10n_util::GetStringUTF16(
248 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON));
252 ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
254 controller_->StartImport(display_name,
261 // TODO(antrim): Code duplication with previous method will be removed once
262 // password sync is implemented.
263 void LocallyManagedUserCreationScreen::ImportManagedUserWithPassword(
264 const std::string& user_id,
265 const std::string& password) {
266 DCHECK(controller_.get());
267 DCHECK(existing_users_.get());
268 VLOG(1) << "Importing user " << user_id;
269 base::DictionaryValue* user_info;
270 if (!existing_users_->GetDictionary(user_id, &user_info)) {
271 LOG(ERROR) << "Can not import non-existing user " << user_id;
274 base::string16 display_name;
275 std::string master_key;
278 int avatar_index = ManagedUserCreationController::kDummyAvatarIndex;
279 user_info->GetString(ManagedUserSyncService::kName, &display_name);
280 user_info->GetString(ManagedUserSyncService::kMasterKey, &master_key);
281 user_info->GetString(ManagedUserSyncService::kChromeOsAvatar, &avatar);
282 user_info->GetBoolean(kUserExists, &exists);
284 // We should not get here with existing user selected, so just display error.
286 actor_->ShowErrorPage(
287 l10n_util::GetStringUTF16(
288 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE),
289 l10n_util::GetStringUTF16(
290 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR),
291 l10n_util::GetStringUTF16(
292 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON));
296 ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
298 controller_->StartImport(display_name,
305 void LocallyManagedUserCreationScreen::OnManagerLoginFailure() {
307 actor_->ShowManagerPasswordError();
310 void LocallyManagedUserCreationScreen::OnManagerFullyAuthenticated(
311 Profile* manager_profile) {
312 DCHECK(controller_.get());
313 // For manager user, move desktop to locked container so that windows created
314 // during the user image picker step are below it.
315 ash::Shell::GetInstance()->
316 desktop_background_controller()->MoveDesktopToLockedContainer();
318 controller_->SetManagerProfile(manager_profile);
320 actor_->ShowUsernamePage();
322 last_page_ = kNameOfNewUserParametersScreen;
324 CommandLine* command_line = CommandLine::ForCurrentProcess();
325 if (!command_line->HasSwitch(::switches::kAllowCreateExistingManagedUsers))
328 ManagedUserSyncServiceFactory::GetForProfile(manager_profile)->
329 GetManagedUsersAsync(base::Bind(
330 &LocallyManagedUserCreationScreen::OnGetManagedUsers,
331 weak_factory_.GetWeakPtr()));
334 void LocallyManagedUserCreationScreen::OnManagerCryptohomeAuthenticated() {
336 actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
337 IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_AUTH_PROGRESS_MESSAGE));
341 void LocallyManagedUserCreationScreen::OnActorDestroyed(
342 LocallyManagedUserCreationScreenHandler* actor) {
347 void LocallyManagedUserCreationScreen::OnCreationError(
348 ManagedUserCreationController::ErrorCode code) {
349 base::string16 title;
350 base::string16 message;
351 base::string16 button;
352 // TODO(antrim) : find out which errors do we really have.
353 // We might reuse some error messages from ordinary user flow.
355 case ManagedUserCreationController::CRYPTOHOME_NO_MOUNT:
356 case ManagedUserCreationController::CRYPTOHOME_FAILED_MOUNT:
357 case ManagedUserCreationController::CRYPTOHOME_FAILED_TPM:
358 title = l10n_util::GetStringUTF16(
359 IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_TITLE);
360 message = l10n_util::GetStringUTF16(
361 IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR);
362 button = l10n_util::GetStringUTF16(
363 IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_BUTTON);
365 case ManagedUserCreationController::CLOUD_SERVER_ERROR:
366 case ManagedUserCreationController::TOKEN_WRITE_FAILED:
367 title = l10n_util::GetStringUTF16(
368 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE);
369 message = l10n_util::GetStringUTF16(
370 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR);
371 button = l10n_util::GetStringUTF16(
372 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON);
374 case ManagedUserCreationController::NO_ERROR:
378 actor_->ShowErrorPage(title, message, button);
381 void LocallyManagedUserCreationScreen::OnCreationTimeout() {
383 actor_->ShowStatusMessage(false /* error */, l10n_util::GetStringUTF16(
384 IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_TIMEOUT_MESSAGE));
388 void LocallyManagedUserCreationScreen::OnLongCreationWarning() {
390 actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
391 IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
395 bool LocallyManagedUserCreationScreen::FindUserByDisplayName(
396 const base::string16& display_name,
397 std::string *out_id) const {
398 if (!existing_users_.get())
400 for (base::DictionaryValue::Iterator it(*existing_users_.get());
401 !it.IsAtEnd(); it.Advance()) {
402 const base::DictionaryValue* user_info =
403 static_cast<const base::DictionaryValue*>(&it.value());
404 base::string16 user_display_name;
405 if (user_info->GetString(ManagedUserSyncService::kName,
406 &user_display_name)) {
407 if (display_name == user_display_name) {
417 // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
418 // It should be removed by issue 251179.
420 void LocallyManagedUserCreationScreen::ApplyPicture() {
421 std::string user_id = controller_->GetManagedUserId();
422 UserManager* user_manager = UserManager::Get();
423 UserImageManager* image_manager = user_manager->GetUserImageManager(user_id);
424 switch (selected_image_) {
425 case User::kExternalImageIndex:
426 // Photo decoding may not have been finished yet.
427 if (user_photo_.isNull()) {
428 apply_photo_after_decoding_ = true;
431 image_manager->SaveUserImage(UserImage::CreateAndEncode(user_photo_));
433 case User::kProfileImageIndex:
434 NOTREACHED() << "Supervised users have no profile pictures";
437 DCHECK(selected_image_ >= 0 && selected_image_ < kDefaultImagesCount);
438 image_manager->SaveUserDefaultImageIndex(selected_image_);
441 // Proceed to tutorial.
442 actor_->ShowTutorialPage();
445 void LocallyManagedUserCreationScreen::OnCreationSuccess() {
449 void LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone(
450 bool is_camera_present) {
452 actor_->SetCameraPresent(is_camera_present);
455 void LocallyManagedUserCreationScreen::OnGetManagedUsers(
456 const base::DictionaryValue* users) {
457 // Copy for passing to WebUI, contains only id, name and avatar URL.
458 scoped_ptr<base::ListValue> ui_users(new base::ListValue());
459 SupervisedUserManager* supervised_user_manager =
460 UserManager::Get()->GetSupervisedUserManager();
462 // Stored copy, contains all necessary information.
463 existing_users_.reset(new base::DictionaryValue());
464 for (base::DictionaryValue::Iterator it(*users); !it.IsAtEnd();
466 // Copy that would be stored in this class.
467 base::DictionaryValue* local_copy =
468 static_cast<base::DictionaryValue*>(it.value().DeepCopy());
469 // Copy that would be passed to WebUI. It has some extra values for
470 // displaying, but does not contain sensitive data, such as master password.
471 base::DictionaryValue* ui_copy =
472 static_cast<base::DictionaryValue*>(new base::DictionaryValue());
474 int avatar_index = ManagedUserCreationController::kDummyAvatarIndex;
475 std::string chromeos_avatar;
476 if (local_copy->GetString(ManagedUserSyncService::kChromeOsAvatar,
478 !chromeos_avatar.empty() &&
479 ManagedUserSyncService::GetAvatarIndex(
480 chromeos_avatar, &avatar_index)) {
481 ui_copy->SetString(kAvatarURLKey, GetDefaultImageUrl(avatar_index));
483 int i = base::RandInt(kFirstDefaultImageIndex, kDefaultImagesCount - 1);
484 local_copy->SetString(
485 ManagedUserSyncService::kChromeOsAvatar,
486 ManagedUserSyncService::BuildAvatarString(i));
487 local_copy->SetBoolean(kRandomAvatarKey, true);
488 ui_copy->SetString(kAvatarURLKey, GetDefaultImageUrl(i));
491 local_copy->SetBoolean(kUserExists, false);
492 ui_copy->SetBoolean(kUserExists, false);
494 base::string16 display_name;
495 local_copy->GetString(ManagedUserSyncService::kName, &display_name);
497 if (supervised_user_manager->FindBySyncId(it.key())) {
498 local_copy->SetBoolean(kUserExists, true);
499 ui_copy->SetBoolean(kUserExists, true);
500 local_copy->SetString(kUserConflict, kUserConflictImported);
501 ui_copy->SetString(kUserConflict, kUserConflictImported);
502 } else if (supervised_user_manager->FindByDisplayName(display_name)) {
503 local_copy->SetBoolean(kUserExists, true);
504 ui_copy->SetBoolean(kUserExists, true);
505 local_copy->SetString(kUserConflict, kUserConflictName);
506 ui_copy->SetString(kUserConflict, kUserConflictName);
508 ui_copy->SetString(ManagedUserSyncService::kName, display_name);
509 // TODO(antrim): For now mark all users as having no password.
510 ui_copy->SetBoolean(kUserNeedPassword, true);
511 ui_copy->SetString("id", it.key());
513 existing_users_->Set(it.key(), local_copy);
514 ui_users->Append(ui_copy);
516 actor_->ShowExistingManagedUsers(ui_users.get());
519 void LocallyManagedUserCreationScreen::OnPhotoTaken(
520 const std::string& raw_data) {
521 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
522 user_photo_ = gfx::ImageSkia();
523 if (image_decoder_.get())
524 image_decoder_->set_delegate(NULL);
525 image_decoder_ = new ImageDecoder(this, raw_data,
526 ImageDecoder::DEFAULT_CODEC);
527 scoped_refptr<base::MessageLoopProxy> task_runner =
528 content::BrowserThread::GetMessageLoopProxyForThread(
529 content::BrowserThread::UI);
530 image_decoder_->Start(task_runner);
533 void LocallyManagedUserCreationScreen::OnImageDecoded(
534 const ImageDecoder* decoder,
535 const SkBitmap& decoded_image) {
536 DCHECK_EQ(image_decoder_.get(), decoder);
537 user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image);
538 if (apply_photo_after_decoding_)
542 void LocallyManagedUserCreationScreen::OnDecodeImageFailed(
543 const ImageDecoder* decoder) {
544 NOTREACHED() << "Failed to decode PNG image from WebUI";
547 void LocallyManagedUserCreationScreen::OnImageSelected(
548 const std::string& image_type,
549 const std::string& image_url) {
550 if (image_url.empty())
552 int user_image_index = User::kInvalidImageIndex;
553 if (image_type == "default" &&
554 IsDefaultImageUrl(image_url, &user_image_index)) {
555 selected_image_ = user_image_index;
556 } else if (image_type == "camera") {
557 selected_image_ = User::kExternalImageIndex;
559 NOTREACHED() << "Unexpected image type: " << image_type;
563 void LocallyManagedUserCreationScreen::OnImageAccepted() {
566 } // namespace chromeos