Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / chromeos / login / managed / locally_managed_user_creation_screen.cc
blob34ea096855f8a1146d83633a9041894e0ba907a1
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"
8 #include "ash/shell.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/locally_managed_user_creation_controller.h"
15 #include "chrome/browser/chromeos/login/screens/error_screen.h"
16 #include "chrome/browser/chromeos/login/screens/screen_observer.h"
17 #include "chrome/browser/chromeos/login/supervised_user_manager.h"
18 #include "chrome/browser/chromeos/login/user_image.h"
19 #include "chrome/browser/chromeos/login/user_image_manager.h"
20 #include "chrome/browser/chromeos/login/wizard_controller.h"
21 #include "chrome/browser/managed_mode/managed_user_sync_service.h"
22 #include "chrome/browser/managed_mode/managed_user_sync_service_factory.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chromeos/network/network_state.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "grit/generated_resources.h"
27 #include "third_party/skia/include/core/SkBitmap.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/gfx/image/image_skia.h"
31 namespace chromeos {
33 namespace {
35 // Key for (boolean) value that indicates that user already exists on device.
36 const char kUserExists[] = "exists";
37 // Key for value that indicates why user can not be imported.
38 const char kUserConflict[] = "conflict";
39 // User is already imported.
40 const char kUserConflictImported[] = "imported";
41 // There is another supervised user with same name.
42 const char kUserConflictName[] = "name";
44 const char kUserNeedPassword[] = "needPassword";
46 const char kAvatarURLKey[] = "avatarurl";
47 const char kRandomAvatarKey[] = "randomAvatar";
48 const char kNameOfIntroScreen[] = "intro";
49 const char kNameOfNewUserParametersScreen[] = "username";
51 void ConfigureErrorScreen(ErrorScreen* screen,
52 const NetworkState* network,
53 const NetworkPortalDetector::CaptivePortalStatus status) {
54 switch (status) {
55 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
56 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
57 NOTREACHED();
58 break;
59 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
60 screen->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
61 std::string());
62 break;
63 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
64 screen->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
65 network->name());
66 screen->FixCaptivePortal();
67 break;
68 case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
69 screen->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
70 std::string());
71 break;
72 default:
73 NOTREACHED();
74 break;
78 } // namespace
80 LocallyManagedUserCreationScreen::LocallyManagedUserCreationScreen(
81 ScreenObserver* observer,
82 LocallyManagedUserCreationScreenHandler* actor)
83 : WizardScreen(observer),
84 weak_factory_(this),
85 actor_(actor),
86 on_error_screen_(false),
87 last_page_(kNameOfIntroScreen),
88 image_decoder_(NULL),
89 apply_photo_after_decoding_(false),
90 selected_image_(0),
91 was_camera_present_(false) {
92 DCHECK(actor_);
93 if (actor_)
94 actor_->SetDelegate(this);
97 LocallyManagedUserCreationScreen::~LocallyManagedUserCreationScreen() {
98 if (actor_)
99 actor_->SetDelegate(NULL);
100 if (image_decoder_.get())
101 image_decoder_->set_delegate(NULL);
102 NetworkPortalDetector::Get()->RemoveObserver(this);
105 void LocallyManagedUserCreationScreen::PrepareToShow() {
106 if (actor_)
107 actor_->PrepareToShow();
110 void LocallyManagedUserCreationScreen::Show() {
111 if (actor_) {
112 actor_->Show();
113 // TODO(antrim) : temorary hack (until upcoming hackaton). Should be
114 // removed once we have screens reworked.
115 if (on_error_screen_)
116 actor_->ShowPage(last_page_);
117 else
118 actor_->ShowIntroPage();
121 if (!on_error_screen_)
122 NetworkPortalDetector::Get()->AddAndFireObserver(this);
123 on_error_screen_ = false;
126 void LocallyManagedUserCreationScreen::OnPageSelected(const std::string& page) {
127 last_page_ = page;
130 void LocallyManagedUserCreationScreen::OnPortalDetectionCompleted(
131 const NetworkState* network,
132 const NetworkPortalDetector::CaptivePortalState& state) {
133 if (state.status == NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE) {
134 get_screen_observer()->HideErrorScreen(this);
135 } else {
136 on_error_screen_ = true;
137 ErrorScreen* screen = get_screen_observer()->GetErrorScreen();
138 ConfigureErrorScreen(screen, network, state.status);
139 screen->SetUIState(ErrorScreen::UI_STATE_LOCALLY_MANAGED);
140 get_screen_observer()->ShowErrorScreen();
144 void LocallyManagedUserCreationScreen::
145 ShowManagerInconsistentStateErrorScreen() {
146 if (!actor_)
147 return;
148 actor_->ShowErrorPage(
149 l10n_util::GetStringUTF16(
150 IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_TITLE),
151 l10n_util::GetStringUTF16(
152 IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE),
153 l10n_util::GetStringUTF16(
154 IDS_CREATE_LOCALLY_MANAGED_USER_MANAGER_INCONSISTENT_STATE_BUTTON));
157 void LocallyManagedUserCreationScreen::ShowInitialScreen() {
158 if (actor_)
159 actor_->ShowIntroPage();
162 void LocallyManagedUserCreationScreen::Hide() {
163 if (actor_)
164 actor_->Hide();
165 if (!on_error_screen_)
166 NetworkPortalDetector::Get()->RemoveObserver(this);
169 std::string LocallyManagedUserCreationScreen::GetName() const {
170 return WizardController::kLocallyManagedUserCreationScreenName;
173 void LocallyManagedUserCreationScreen::AbortFlow() {
174 controller_->CancelCreation();
177 void LocallyManagedUserCreationScreen::FinishFlow() {
178 controller_->FinishCreation();
181 void LocallyManagedUserCreationScreen::AuthenticateManager(
182 const std::string& manager_id,
183 const std::string& manager_password) {
184 // Make sure no two controllers exist at the same time.
185 controller_.reset();
186 controller_.reset(new LocallyManagedUserCreationController(this, manager_id));
188 ExistingUserController::current_controller()->
189 Login(UserContext(manager_id,
190 manager_password,
191 std::string() /* auth_code */));
194 void LocallyManagedUserCreationScreen::CreateManagedUser(
195 const base::string16& display_name,
196 const std::string& managed_user_password) {
197 DCHECK(controller_.get());
198 int image;
199 if (selected_image_ == User::kExternalImageIndex)
200 // TODO(dzhioev): crbug/249660
201 image = LocallyManagedUserCreationController::kDummyAvatarIndex;
202 else
203 image = selected_image_;
204 controller_->SetUpCreation(display_name, managed_user_password, image);
205 controller_->StartCreation();
208 void LocallyManagedUserCreationScreen::ImportManagedUser(
209 const std::string& user_id) {
210 DCHECK(controller_.get());
211 DCHECK(existing_users_.get());
212 VLOG(1) << "Importing user " << user_id;
213 base::DictionaryValue* user_info;
214 if (!existing_users_->GetDictionary(user_id, &user_info)) {
215 LOG(ERROR) << "Can not import non-existing user " << user_id;
216 return;
218 base::string16 display_name;
219 std::string master_key;
220 std::string avatar;
221 bool exists;
222 int avatar_index = LocallyManagedUserCreationController::kDummyAvatarIndex;
223 user_info->GetString(ManagedUserSyncService::kName, &display_name);
224 user_info->GetString(ManagedUserSyncService::kMasterKey, &master_key);
225 user_info->GetString(ManagedUserSyncService::kChromeOsAvatar, &avatar);
226 user_info->GetBoolean(kUserExists, &exists);
228 // We should not get here with existing user selected, so just display error.
229 if (exists) {
230 actor_->ShowErrorPage(
231 l10n_util::GetStringUTF16(
232 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE),
233 l10n_util::GetStringUTF16(
234 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR),
235 l10n_util::GetStringUTF16(
236 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON));
237 return;
240 ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
242 controller_->StartImport(display_name,
243 std::string(),
244 avatar_index,
245 user_id,
246 master_key);
249 // TODO(antrim): Code duplication with previous method will be removed once
250 // password sync is implemented.
251 void LocallyManagedUserCreationScreen::ImportManagedUserWithPassword(
252 const std::string& user_id,
253 const std::string& password) {
254 DCHECK(controller_.get());
255 DCHECK(existing_users_.get());
256 VLOG(1) << "Importing user " << user_id;
257 base::DictionaryValue* user_info;
258 if (!existing_users_->GetDictionary(user_id, &user_info)) {
259 LOG(ERROR) << "Can not import non-existing user " << user_id;
260 return;
262 base::string16 display_name;
263 std::string master_key;
264 std::string avatar;
265 bool exists;
266 int avatar_index = LocallyManagedUserCreationController::kDummyAvatarIndex;
267 user_info->GetString(ManagedUserSyncService::kName, &display_name);
268 user_info->GetString(ManagedUserSyncService::kMasterKey, &master_key);
269 user_info->GetString(ManagedUserSyncService::kChromeOsAvatar, &avatar);
270 user_info->GetBoolean(kUserExists, &exists);
272 // We should not get here with existing user selected, so just display error.
273 if (exists) {
274 actor_->ShowErrorPage(
275 l10n_util::GetStringUTF16(
276 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE),
277 l10n_util::GetStringUTF16(
278 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR),
279 l10n_util::GetStringUTF16(
280 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON));
281 return;
284 ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
286 controller_->StartImport(display_name,
287 password,
288 avatar_index,
289 user_id,
290 master_key);
293 void LocallyManagedUserCreationScreen::OnManagerLoginFailure() {
294 if (actor_)
295 actor_->ShowManagerPasswordError();
298 void LocallyManagedUserCreationScreen::OnManagerFullyAuthenticated(
299 Profile* manager_profile) {
300 DCHECK(controller_.get());
301 // For manager user, move desktop to locked container so that windows created
302 // during the user image picker step are below it.
303 ash::Shell::GetInstance()->
304 desktop_background_controller()->MoveDesktopToLockedContainer();
306 controller_->SetManagerProfile(manager_profile);
307 if (actor_)
308 actor_->ShowUsernamePage();
310 last_page_ = kNameOfNewUserParametersScreen;
312 CommandLine* command_line = CommandLine::ForCurrentProcess();
313 if (!command_line->HasSwitch(::switches::kAllowCreateExistingManagedUsers))
314 return;
316 ManagedUserSyncServiceFactory::GetForProfile(manager_profile)->
317 GetManagedUsersAsync(base::Bind(
318 &LocallyManagedUserCreationScreen::OnGetManagedUsers,
319 weak_factory_.GetWeakPtr()));
322 void LocallyManagedUserCreationScreen::OnManagerCryptohomeAuthenticated() {
323 if (actor_) {
324 actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
325 IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_AUTH_PROGRESS_MESSAGE));
329 void LocallyManagedUserCreationScreen::OnActorDestroyed(
330 LocallyManagedUserCreationScreenHandler* actor) {
331 if (actor_ == actor)
332 actor_ = NULL;
335 void LocallyManagedUserCreationScreen::OnCreationError(
336 LocallyManagedUserCreationController::ErrorCode code) {
337 base::string16 title;
338 base::string16 message;
339 base::string16 button;
340 // TODO(antrim) : find out which errors do we really have.
341 // We might reuse some error messages from ordinary user flow.
342 switch (code) {
343 case LocallyManagedUserCreationController::CRYPTOHOME_NO_MOUNT:
344 case LocallyManagedUserCreationController::CRYPTOHOME_FAILED_MOUNT:
345 case LocallyManagedUserCreationController::CRYPTOHOME_FAILED_TPM:
346 title = l10n_util::GetStringUTF16(
347 IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_TITLE);
348 message = l10n_util::GetStringUTF16(
349 IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR);
350 button = l10n_util::GetStringUTF16(
351 IDS_CREATE_LOCALLY_MANAGED_USER_TPM_ERROR_BUTTON);
352 break;
353 case LocallyManagedUserCreationController::CLOUD_SERVER_ERROR:
354 case LocallyManagedUserCreationController::TOKEN_WRITE_FAILED:
355 title = l10n_util::GetStringUTF16(
356 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_TITLE);
357 message = l10n_util::GetStringUTF16(
358 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR);
359 button = l10n_util::GetStringUTF16(
360 IDS_CREATE_LOCALLY_MANAGED_USER_GENERIC_ERROR_BUTTON);
361 break;
362 case LocallyManagedUserCreationController::NO_ERROR:
363 NOTREACHED();
365 if (actor_)
366 actor_->ShowErrorPage(title, message, button);
369 void LocallyManagedUserCreationScreen::OnCreationTimeout() {
370 if (actor_) {
371 actor_->ShowStatusMessage(false /* error */, l10n_util::GetStringUTF16(
372 IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_TIMEOUT_MESSAGE));
376 void LocallyManagedUserCreationScreen::OnLongCreationWarning() {
377 if (actor_) {
378 actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
379 IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
383 bool LocallyManagedUserCreationScreen::FindUserByDisplayName(
384 const base::string16& display_name,
385 std::string *out_id) const {
386 if (!existing_users_.get())
387 return false;
388 for (base::DictionaryValue::Iterator it(*existing_users_.get());
389 !it.IsAtEnd(); it.Advance()) {
390 const base::DictionaryValue* user_info =
391 static_cast<const base::DictionaryValue*>(&it.value());
392 base::string16 user_display_name;
393 if (user_info->GetString(ManagedUserSyncService::kName,
394 &user_display_name)) {
395 if (display_name == user_display_name) {
396 if (out_id)
397 *out_id = it.key();
398 return true;
402 return false;
405 // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
406 // It should be removed by issue 251179.
408 void LocallyManagedUserCreationScreen::ApplyPicture() {
409 std::string user_id = controller_->GetManagedUserId();
410 UserManager* user_manager = UserManager::Get();
411 UserImageManager* image_manager = user_manager->GetUserImageManager(user_id);
412 switch (selected_image_) {
413 case User::kExternalImageIndex:
414 // Photo decoding may not have been finished yet.
415 if (user_photo_.isNull()) {
416 apply_photo_after_decoding_ = true;
417 return;
419 image_manager->SaveUserImage(UserImage::CreateAndEncode(user_photo_));
420 break;
421 case User::kProfileImageIndex:
422 NOTREACHED() << "Supervised users have no profile pictures";
423 break;
424 default:
425 DCHECK(selected_image_ >= 0 && selected_image_ < kDefaultImagesCount);
426 image_manager->SaveUserDefaultImageIndex(selected_image_);
427 break;
429 // Proceed to tutorial.
430 actor_->ShowTutorialPage();
433 void LocallyManagedUserCreationScreen::OnCreationSuccess() {
434 ApplyPicture();
437 void LocallyManagedUserCreationScreen::CheckCameraPresence() {
438 CameraDetector::StartPresenceCheck(
439 base::Bind(&LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone,
440 weak_factory_.GetWeakPtr()));
443 void LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone() {
444 bool is_camera_present = CameraDetector::camera_presence() ==
445 CameraDetector::kCameraPresent;
446 if (actor_) {
447 if (is_camera_present != was_camera_present_) {
448 actor_->SetCameraPresent(is_camera_present);
449 was_camera_present_ = is_camera_present;
454 void LocallyManagedUserCreationScreen::OnGetManagedUsers(
455 const base::DictionaryValue* users) {
456 // Copy for passing to WebUI, contains only id, name and avatar URL.
457 scoped_ptr<base::ListValue> ui_users(new base::ListValue());
458 SupervisedUserManager* supervised_user_manager =
459 UserManager::Get()->GetSupervisedUserManager();
461 // Stored copy, contains all necessary information.
462 existing_users_.reset(new base::DictionaryValue());
463 for (base::DictionaryValue::Iterator it(*users); !it.IsAtEnd();
464 it.Advance()) {
465 // Copy that would be stored in this class.
466 base::DictionaryValue* local_copy =
467 static_cast<base::DictionaryValue*>(it.value().DeepCopy());
468 // Copy that would be passed to WebUI. It has some extra values for
469 // displaying, but does not contain sensitive data, such as master password.
470 base::DictionaryValue* ui_copy =
471 static_cast<base::DictionaryValue*>(new base::DictionaryValue());
473 int avatar_index = LocallyManagedUserCreationController::kDummyAvatarIndex;
474 std::string chromeos_avatar;
475 if (local_copy->GetString(ManagedUserSyncService::kChromeOsAvatar,
476 &chromeos_avatar) &&
477 !chromeos_avatar.empty() &&
478 ManagedUserSyncService::GetAvatarIndex(
479 chromeos_avatar, &avatar_index)) {
480 ui_copy->SetString(kAvatarURLKey, GetDefaultImageUrl(avatar_index));
481 } else {
482 int i = base::RandInt(kFirstDefaultImageIndex, kDefaultImagesCount - 1);
483 local_copy->SetString(
484 ManagedUserSyncService::kChromeOsAvatar,
485 ManagedUserSyncService::BuildAvatarString(i));
486 local_copy->SetBoolean(kRandomAvatarKey, true);
487 ui_copy->SetString(kAvatarURLKey, GetDefaultImageUrl(i));
490 local_copy->SetBoolean(kUserExists, false);
491 ui_copy->SetBoolean(kUserExists, false);
493 base::string16 display_name;
494 local_copy->GetString(ManagedUserSyncService::kName, &display_name);
496 if (supervised_user_manager->FindBySyncId(it.key())) {
497 local_copy->SetBoolean(kUserExists, true);
498 ui_copy->SetBoolean(kUserExists, true);
499 local_copy->SetString(kUserConflict, kUserConflictImported);
500 ui_copy->SetString(kUserConflict, kUserConflictImported);
501 } else if (supervised_user_manager->FindByDisplayName(display_name)) {
502 local_copy->SetBoolean(kUserExists, true);
503 ui_copy->SetBoolean(kUserExists, true);
504 local_copy->SetString(kUserConflict, kUserConflictName);
505 ui_copy->SetString(kUserConflict, kUserConflictName);
507 ui_copy->SetString(ManagedUserSyncService::kName, display_name);
508 // TODO(antrim): For now mark all users as having no password.
509 ui_copy->SetBoolean(kUserNeedPassword, true);
510 ui_copy->SetString("id", it.key());
512 existing_users_->Set(it.key(), local_copy);
513 ui_users->Append(ui_copy);
515 actor_->ShowExistingManagedUsers(ui_users.get());
518 void LocallyManagedUserCreationScreen::OnPhotoTaken(
519 const std::string& raw_data) {
520 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
521 user_photo_ = gfx::ImageSkia();
522 if (image_decoder_.get())
523 image_decoder_->set_delegate(NULL);
524 image_decoder_ = new ImageDecoder(this, raw_data,
525 ImageDecoder::DEFAULT_CODEC);
526 scoped_refptr<base::MessageLoopProxy> task_runner =
527 content::BrowserThread::GetMessageLoopProxyForThread(
528 content::BrowserThread::UI);
529 image_decoder_->Start(task_runner);
532 void LocallyManagedUserCreationScreen::OnImageDecoded(
533 const ImageDecoder* decoder,
534 const SkBitmap& decoded_image) {
535 DCHECK_EQ(image_decoder_.get(), decoder);
536 user_photo_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image);
537 if (apply_photo_after_decoding_)
538 ApplyPicture();
541 void LocallyManagedUserCreationScreen::OnDecodeImageFailed(
542 const ImageDecoder* decoder) {
543 NOTREACHED() << "Failed to decode PNG image from WebUI";
546 void LocallyManagedUserCreationScreen::OnImageSelected(
547 const std::string& image_type,
548 const std::string& image_url) {
549 if (image_url.empty())
550 return;
551 int user_image_index = User::kInvalidImageIndex;
552 if (image_type == "default" &&
553 IsDefaultImageUrl(image_url, &user_image_index)) {
554 selected_image_ = user_image_index;
555 } else if (image_type == "camera") {
556 selected_image_ = User::kExternalImageIndex;
557 } else {
558 NOTREACHED() << "Unexpected image type: " << image_type;
562 void LocallyManagedUserCreationScreen::OnImageAccepted() {
565 } // namespace chromeos