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() {
101 actor_->SetDelegate(NULL);
102 if (image_decoder_.get())
103 image_decoder_->set_delegate(NULL);
104 NetworkPortalDetector::Get()->RemoveObserver(this);
107 void LocallyManagedUserCreationScreen::PrepareToShow() {
109 actor_->PrepareToShow();
112 void LocallyManagedUserCreationScreen::Show() {
115 // TODO(antrim) : temorary hack (until upcoming hackaton). Should be
116 // removed once we have screens reworked.
117 if (on_error_screen_)
118 actor_->ShowPage(last_page_);
120 actor_->ShowIntroPage();
123 if (!on_error_screen_)
124 NetworkPortalDetector::Get()->AddAndFireObserver(this);
125 on_error_screen_ = false;
128 void LocallyManagedUserCreationScreen::OnPageSelected(const std::string& page) {
132 void LocallyManagedUserCreationScreen::OnPortalDetectionCompleted(
133 const NetworkState* network,
134 const NetworkPortalDetector::CaptivePortalState& state) {
135 if (state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) {
136 get_screen_observer()->HideErrorScreen(this);
138 on_error_screen_ = true;
139 ErrorScreen* screen = get_screen_observer()->GetErrorScreen();
140 ConfigureErrorScreen(screen, network, state.status);
141 screen->SetUIState(ErrorScreen::UI_STATE_LOCALLY_MANAGED);
142 get_screen_observer()->ShowErrorScreen();
146 void LocallyManagedUserCreationScreen::
147 ShowManagerInconsistentStateErrorScreen() {
150 actor_->ShowErrorPage(
151 l10n_util::GetStringUTF16(
152 IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_TITLE),
153 l10n_util::GetStringUTF16(
154 IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE),
155 l10n_util::GetStringUTF16(
156 IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_BUTTON));
159 void LocallyManagedUserCreationScreen::ShowInitialScreen() {
161 actor_->ShowIntroPage();
164 void LocallyManagedUserCreationScreen::Hide() {
167 if (!on_error_screen_)
168 NetworkPortalDetector::Get()->RemoveObserver(this);
171 std::string LocallyManagedUserCreationScreen::GetName() const {
172 return WizardController::kLocallyManagedUserCreationScreenName;
175 void LocallyManagedUserCreationScreen::AbortFlow() {
176 controller_->CancelCreation();
179 void LocallyManagedUserCreationScreen::FinishFlow() {
180 controller_->FinishCreation();
183 void LocallyManagedUserCreationScreen::AuthenticateManager(
184 const std::string& manager_id,
185 const std::string& manager_password) {
186 // Make sure no two controllers exist at the same time.
188 SupervisedUserAuthentication* authentication =
189 UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
191 if (authentication->GetStableSchema() ==
192 SupervisedUserAuthentication::SCHEMA_PLAIN) {
193 controller_.reset(new ManagedUserCreationControllerOld(this, manager_id));
195 controller_.reset(new ManagedUserCreationControllerNew(this, manager_id));
198 ExistingUserController::current_controller()->
199 Login(UserContext(manager_id,
201 std::string() /* auth_code */));
204 void LocallyManagedUserCreationScreen::CreateManagedUser(
205 const base::string16& display_name,
206 const std::string& managed_user_password) {
207 DCHECK(controller_.get());
209 if (selected_image_ == User::kExternalImageIndex)
210 // TODO(dzhioev): crbug/249660
211 image = ManagedUserCreationController::kDummyAvatarIndex;
213 image = selected_image_;
214 controller_->StartCreation(display_name, managed_user_password, image);
217 void LocallyManagedUserCreationScreen::ImportManagedUser(
218 const std::string& user_id) {
219 DCHECK(controller_.get());
220 DCHECK(existing_users_.get());
221 VLOG(1) << "Importing user " << user_id;
222 base::DictionaryValue* user_info;
223 if (!existing_users_->GetDictionary(user_id, &user_info)) {
224 LOG(ERROR) << "Can not import non-existing user " << user_id;
227 base::string16 display_name;
228 std::string master_key;
231 int avatar_index = ManagedUserCreationController::kDummyAvatarIndex;
232 user_info->GetString(ManagedUserSyncService::kName, &display_name);
233 user_info->GetString(ManagedUserSyncService::kMasterKey, &master_key);
234 user_info->GetString(ManagedUserSyncService::kChromeOsAvatar, &avatar);
235 user_info->GetBoolean(kUserExists, &exists);
237 // We should not get here with existing user selected, so just display error.
239 actor_->ShowErrorPage(
240 l10n_util::GetStringUTF16(
241 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE),
242 l10n_util::GetStringUTF16(
243 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR),
244 l10n_util::GetStringUTF16(
245 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON));
249 ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
251 controller_->StartImport(display_name,
258 // TODO(antrim): Code duplication with previous method will be removed once
259 // password sync is implemented.
260 void LocallyManagedUserCreationScreen::ImportManagedUserWithPassword(
261 const std::string& user_id,
262 const std::string& password) {
263 DCHECK(controller_.get());
264 DCHECK(existing_users_.get());
265 VLOG(1) << "Importing user " << user_id;
266 base::DictionaryValue* user_info;
267 if (!existing_users_->GetDictionary(user_id, &user_info)) {
268 LOG(ERROR) << "Can not import non-existing user " << user_id;
271 base::string16 display_name;
272 std::string master_key;
275 int avatar_index = ManagedUserCreationController::kDummyAvatarIndex;
276 user_info->GetString(ManagedUserSyncService::kName, &display_name);
277 user_info->GetString(ManagedUserSyncService::kMasterKey, &master_key);
278 user_info->GetString(ManagedUserSyncService::kChromeOsAvatar, &avatar);
279 user_info->GetBoolean(kUserExists, &exists);
281 // We should not get here with existing user selected, so just display error.
283 actor_->ShowErrorPage(
284 l10n_util::GetStringUTF16(
285 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE),
286 l10n_util::GetStringUTF16(
287 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR),
288 l10n_util::GetStringUTF16(
289 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON));
293 ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
295 controller_->StartImport(display_name,
302 void LocallyManagedUserCreationScreen::OnManagerLoginFailure() {
304 actor_->ShowManagerPasswordError();
307 void LocallyManagedUserCreationScreen::OnManagerFullyAuthenticated(
308 Profile* manager_profile) {
309 DCHECK(controller_.get());
310 // For manager user, move desktop to locked container so that windows created
311 // during the user image picker step are below it.
312 ash::Shell::GetInstance()->
313 desktop_background_controller()->MoveDesktopToLockedContainer();
315 controller_->SetManagerProfile(manager_profile);
317 actor_->ShowUsernamePage();
319 last_page_ = kNameOfNewUserParametersScreen;
321 CommandLine* command_line = CommandLine::ForCurrentProcess();
322 if (!command_line->HasSwitch(::switches::kAllowCreateExistingManagedUsers))
325 ManagedUserSyncServiceFactory::GetForProfile(manager_profile)->
326 GetManagedUsersAsync(base::Bind(
327 &LocallyManagedUserCreationScreen::OnGetManagedUsers,
328 weak_factory_.GetWeakPtr()));
331 void LocallyManagedUserCreationScreen::OnManagerCryptohomeAuthenticated() {
333 actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
334 IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_AUTH_PROGRESS_MESSAGE));
338 void LocallyManagedUserCreationScreen::OnActorDestroyed(
339 LocallyManagedUserCreationScreenHandler* actor) {
344 void LocallyManagedUserCreationScreen::OnCreationError(
345 ManagedUserCreationController::ErrorCode code) {
346 base::string16 title;
347 base::string16 message;
348 base::string16 button;
349 // TODO(antrim) : find out which errors do we really have.
350 // We might reuse some error messages from ordinary user flow.
352 case ManagedUserCreationController::CRYPTOHOME_NO_MOUNT:
353 case ManagedUserCreationController::CRYPTOHOME_FAILED_MOUNT:
354 case ManagedUserCreationController::CRYPTOHOME_FAILED_TPM:
355 title = l10n_util::GetStringUTF16(
356 IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_TITLE);
357 message = l10n_util::GetStringUTF16(
358 IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR);
359 button = l10n_util::GetStringUTF16(
360 IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_BUTTON);
362 case ManagedUserCreationController::CLOUD_SERVER_ERROR:
363 case ManagedUserCreationController::TOKEN_WRITE_FAILED:
364 title = l10n_util::GetStringUTF16(
365 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE);
366 message = l10n_util::GetStringUTF16(
367 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR);
368 button = l10n_util::GetStringUTF16(
369 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON);
371 case ManagedUserCreationController::NO_ERROR:
375 actor_->ShowErrorPage(title, message, button);
378 void LocallyManagedUserCreationScreen::OnCreationTimeout() {
380 actor_->ShowStatusMessage(false /* error */, l10n_util::GetStringUTF16(
381 IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_TIMEOUT_MESSAGE));
385 void LocallyManagedUserCreationScreen::OnLongCreationWarning() {
387 actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
388 IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
392 bool LocallyManagedUserCreationScreen::FindUserByDisplayName(
393 const base::string16& display_name,
394 std::string *out_id) const {
395 if (!existing_users_.get())
397 for (base::DictionaryValue::Iterator it(*existing_users_.get());
398 !it.IsAtEnd(); it.Advance()) {
399 const base::DictionaryValue* user_info =
400 static_cast<const base::DictionaryValue*>(&it.value());
401 base::string16 user_display_name;
402 if (user_info->GetString(ManagedUserSyncService::kName,
403 &user_display_name)) {
404 if (display_name == user_display_name) {
414 // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
415 // It should be removed by issue 251179.
417 void LocallyManagedUserCreationScreen::ApplyPicture() {
418 std::string user_id = controller_->GetManagedUserId();
419 UserManager* user_manager = UserManager::Get();
420 UserImageManager* image_manager = user_manager->GetUserImageManager(user_id);
421 switch (selected_image_) {
422 case User::kExternalImageIndex:
423 // Photo decoding may not have been finished yet.
424 if (user_photo_.isNull()) {
425 apply_photo_after_decoding_ = true;
428 image_manager->SaveUserImage(UserImage::CreateAndEncode(user_photo_));
430 case User::kProfileImageIndex:
431 NOTREACHED() << "Supervised users have no profile pictures";
434 DCHECK(selected_image_ >= 0 && selected_image_ < kDefaultImagesCount);
435 image_manager->SaveUserDefaultImageIndex(selected_image_);
438 // Proceed to tutorial.
439 actor_->ShowTutorialPage();
442 void LocallyManagedUserCreationScreen::OnCreationSuccess() {
446 void LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone(
447 bool is_camera_present) {
449 actor_->SetCameraPresent(is_camera_present);
452 void LocallyManagedUserCreationScreen::OnGetManagedUsers(
453 const base::DictionaryValue* users) {
454 // Copy for passing to WebUI, contains only id, name and avatar URL.
455 scoped_ptr<base::ListValue> ui_users(new base::ListValue());
456 SupervisedUserManager* supervised_user_manager =
457 UserManager::Get()->GetSupervisedUserManager();
459 // Stored copy, contains all necessary information.
460 existing_users_.reset(new base::DictionaryValue());
461 for (base::DictionaryValue::Iterator it(*users); !it.IsAtEnd();
463 // Copy that would be stored in this class.
464 base::DictionaryValue* local_copy =
465 static_cast<base::DictionaryValue*>(it.value().DeepCopy());
466 // Copy that would be passed to WebUI. It has some extra values for
467 // displaying, but does not contain sensitive data, such as master password.
468 base::DictionaryValue* ui_copy =
469 static_cast<base::DictionaryValue*>(new base::DictionaryValue());
471 int avatar_index = ManagedUserCreationController::kDummyAvatarIndex;
472 std::string chromeos_avatar;
473 if (local_copy->GetString(ManagedUserSyncService::kChromeOsAvatar,
475 !chromeos_avatar.empty() &&
476 ManagedUserSyncService::GetAvatarIndex(
477 chromeos_avatar, &avatar_index)) {
478 ui_copy->SetString(kAvatarURLKey, GetDefaultImageUrl(avatar_index));
480 int i = base::RandInt(kFirstDefaultImageIndex, kDefaultImagesCount - 1);
481 local_copy->SetString(
482 ManagedUserSyncService::kChromeOsAvatar,
483 ManagedUserSyncService::BuildAvatarString(i));
484 local_copy->SetBoolean(kRandomAvatarKey, true);
485 ui_copy->SetString(kAvatarURLKey, GetDefaultImageUrl(i));
488 local_copy->SetBoolean(kUserExists, false);
489 ui_copy->SetBoolean(kUserExists, false);
491 base::string16 display_name;
492 local_copy->GetString(ManagedUserSyncService::kName, &display_name);
494 if (supervised_user_manager->FindBySyncId(it.key())) {
495 local_copy->SetBoolean(kUserExists, true);
496 ui_copy->SetBoolean(kUserExists, true);
497 local_copy->SetString(kUserConflict, kUserConflictImported);
498 ui_copy->SetString(kUserConflict, kUserConflictImported);
499 } else if (supervised_user_manager->FindByDisplayName(display_name)) {
500 local_copy->SetBoolean(kUserExists, true);
501 ui_copy->SetBoolean(kUserExists, true);
502 local_copy->SetString(kUserConflict, kUserConflictName);
503 ui_copy->SetString(kUserConflict, kUserConflictName);
505 ui_copy->SetString(ManagedUserSyncService::kName, display_name);
506 // TODO(antrim): For now mark all users as having no password.
507 ui_copy->SetBoolean(kUserNeedPassword, true);
508 ui_copy->SetString("id", it.key());
510 existing_users_->Set(it.key(), local_copy);
511 ui_users->Append(ui_copy);
513 actor_->ShowExistingManagedUsers(ui_users.get());
516 void LocallyManagedUserCreationScreen::OnPhotoTaken(
517 const std::string& raw_data) {
518 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
519 user_photo_ = gfx::ImageSkia();
520 if (image_decoder_.get())
521 image_decoder_->set_delegate(NULL);
522 image_decoder_ = new ImageDecoder(this, raw_data,
523 ImageDecoder::DEFAULT_CODEC);
524 scoped_refptr<base::MessageLoopProxy> task_runner =
525 content::BrowserThread::GetMessageLoopProxyForThread(
526 content::BrowserThread::UI);
527 image_decoder_->Start(task_runner);
530 void LocallyManagedUserCreationScreen::OnImageDecoded(
531 const ImageDecoder* decoder,
532 const SkBitmap& decoded_image) {
533 DCHECK_EQ(image_decoder_.get(), decoder);
534 user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image);
535 if (apply_photo_after_decoding_)
539 void LocallyManagedUserCreationScreen::OnDecodeImageFailed(
540 const ImageDecoder* decoder) {
541 NOTREACHED() << "Failed to decode PNG image from WebUI";
544 void LocallyManagedUserCreationScreen::OnImageSelected(
545 const std::string& image_type,
546 const std::string& image_url) {
547 if (image_url.empty())
549 int user_image_index = User::kInvalidImageIndex;
550 if (image_type == "default" &&
551 IsDefaultImageUrl(image_url, &user_image_index)) {
552 selected_image_ = user_image_index;
553 } else if (image_type == "camera") {
554 selected_image_ = User::kExternalImageIndex;
556 NOTREACHED() << "Unexpected image type: " << image_type;
560 void LocallyManagedUserCreationScreen::OnImageAccepted() {
563 } // namespace chromeos