Upstream version 6.35.121.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / login / managed / locally_managed_user_creation_screen.cc
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.
4
5 #include "chrome/browser/chromeos/login/managed/locally_managed_user_creation_screen.h"
6
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/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"
33
34 namespace chromeos {
35
36 namespace {
37
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";
46
47 const char kUserNeedPassword[] = "needPassword";
48
49 const char kAvatarURLKey[] = "avatarurl";
50 const char kRandomAvatarKey[] = "randomAvatar";
51 const char kNameOfIntroScreen[] = "intro";
52 const char kNameOfNewUserParametersScreen[] = "username";
53
54 void ConfigureErrorScreen(ErrorScreen* screen,
55     const NetworkState* network,
56     const NetworkPortalDetector::CaptivePortalStatus status) {
57   switch (status) {
58     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN:
59     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE:
60       NOTREACHED();
61       break;
62     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE:
63       screen->SetErrorState(ErrorScreen::ERROR_STATE_OFFLINE,
64                             std::string());
65       break;
66     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL:
67       screen->SetErrorState(ErrorScreen::ERROR_STATE_PORTAL,
68                             network ? network->name() : std::string());
69       screen->FixCaptivePortal();
70       break;
71     case NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED:
72       screen->SetErrorState(ErrorScreen::ERROR_STATE_PROXY,
73                             std::string());
74       break;
75     default:
76       NOTREACHED();
77       break;
78   }
79 }
80
81 } // namespace
82
83 LocallyManagedUserCreationScreen::LocallyManagedUserCreationScreen(
84     ScreenObserver* observer,
85     LocallyManagedUserCreationScreenHandler* actor)
86     : WizardScreen(observer),
87       weak_factory_(this),
88       actor_(actor),
89       on_error_screen_(false),
90       last_page_(kNameOfIntroScreen),
91       image_decoder_(NULL),
92       apply_photo_after_decoding_(false),
93       selected_image_(0) {
94   DCHECK(actor_);
95   if (actor_)
96     actor_->SetDelegate(this);
97 }
98
99 LocallyManagedUserCreationScreen::~LocallyManagedUserCreationScreen() {
100   if (actor_)
101     actor_->SetDelegate(NULL);
102   if (image_decoder_.get())
103     image_decoder_->set_delegate(NULL);
104   NetworkPortalDetector::Get()->RemoveObserver(this);
105 }
106
107 void LocallyManagedUserCreationScreen::PrepareToShow() {
108   if (actor_)
109     actor_->PrepareToShow();
110 }
111
112 void LocallyManagedUserCreationScreen::Show() {
113   if (actor_) {
114     actor_->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_);
119     else
120       actor_->ShowIntroPage();
121   }
122
123   if (!on_error_screen_)
124     NetworkPortalDetector::Get()->AddAndFireObserver(this);
125   on_error_screen_ = false;
126 }
127
128 void LocallyManagedUserCreationScreen::OnPageSelected(const std::string& page) {
129   last_page_ = page;
130 }
131
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);
137   } else {
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();
143   }
144 }
145
146 void LocallyManagedUserCreationScreen::
147     ShowManagerInconsistentStateErrorScreen() {
148   if (!actor_)
149     return;
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));
157 }
158
159 void LocallyManagedUserCreationScreen::ShowInitialScreen() {
160   if (actor_)
161     actor_->ShowIntroPage();
162 }
163
164 void LocallyManagedUserCreationScreen::Hide() {
165   if (actor_)
166     actor_->Hide();
167   if (!on_error_screen_)
168     NetworkPortalDetector::Get()->RemoveObserver(this);
169 }
170
171 std::string LocallyManagedUserCreationScreen::GetName() const {
172   return WizardController::kLocallyManagedUserCreationScreenName;
173 }
174
175 void LocallyManagedUserCreationScreen::AbortFlow() {
176   controller_->CancelCreation();
177 }
178
179 void LocallyManagedUserCreationScreen::FinishFlow() {
180   controller_->FinishCreation();
181 }
182
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.
187   controller_.reset();
188   SupervisedUserAuthentication* authentication =
189       UserManager::Get()->GetSupervisedUserManager()->GetAuthentication();
190
191   if (authentication->GetStableSchema() ==
192       SupervisedUserAuthentication::SCHEMA_PLAIN) {
193     controller_.reset(new ManagedUserCreationControllerOld(this, manager_id));
194   } else {
195     controller_.reset(new ManagedUserCreationControllerNew(this, manager_id));
196   }
197
198   ExistingUserController::current_controller()->
199       Login(UserContext(manager_id,
200                         manager_password,
201                         std::string()  /* auth_code */));
202 }
203
204 void LocallyManagedUserCreationScreen::CreateManagedUser(
205     const base::string16& display_name,
206     const std::string& managed_user_password) {
207   DCHECK(controller_.get());
208   int image;
209   if (selected_image_ == User::kExternalImageIndex)
210     // TODO(dzhioev): crbug/249660
211     image = ManagedUserCreationController::kDummyAvatarIndex;
212   else
213     image = selected_image_;
214   controller_->StartCreation(display_name, managed_user_password, image);
215 }
216
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;
225     return;
226   }
227   base::string16 display_name;
228   std::string master_key;
229   std::string avatar;
230   bool exists;
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);
236
237   // We should not get here with existing user selected, so just display error.
238   if (exists) {
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));
246     return;
247   }
248
249   ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
250
251   controller_->StartImport(display_name,
252                            std::string(),
253                            avatar_index,
254                            user_id,
255                            master_key);
256 }
257
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;
269     return;
270   }
271   base::string16 display_name;
272   std::string master_key;
273   std::string avatar;
274   bool exists;
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);
280
281   // We should not get here with existing user selected, so just display error.
282   if (exists) {
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));
290     return;
291   }
292
293   ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
294
295   controller_->StartImport(display_name,
296                            password,
297                            avatar_index,
298                            user_id,
299                            master_key);
300 }
301
302 void LocallyManagedUserCreationScreen::OnManagerLoginFailure() {
303   if (actor_)
304     actor_->ShowManagerPasswordError();
305 }
306
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();
314
315   controller_->SetManagerProfile(manager_profile);
316   if (actor_)
317     actor_->ShowUsernamePage();
318
319   last_page_ = kNameOfNewUserParametersScreen;
320
321   CommandLine* command_line = CommandLine::ForCurrentProcess();
322   if (!command_line->HasSwitch(::switches::kAllowCreateExistingManagedUsers))
323     return;
324
325   ManagedUserSyncServiceFactory::GetForProfile(manager_profile)->
326       GetManagedUsersAsync(base::Bind(
327           &LocallyManagedUserCreationScreen::OnGetManagedUsers,
328           weak_factory_.GetWeakPtr()));
329 }
330
331 void LocallyManagedUserCreationScreen::OnManagerCryptohomeAuthenticated() {
332   if (actor_) {
333     actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
334             IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_AUTH_PROGRESS_MESSAGE));
335   }
336 }
337
338 void LocallyManagedUserCreationScreen::OnActorDestroyed(
339     LocallyManagedUserCreationScreenHandler* actor) {
340   if (actor_ == actor)
341     actor_ = NULL;
342 }
343
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.
351   switch (code) {
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);
361       break;
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);
370       break;
371     case ManagedUserCreationController::NO_ERROR:
372       NOTREACHED();
373   }
374   if (actor_)
375     actor_->ShowErrorPage(title, message, button);
376 }
377
378 void LocallyManagedUserCreationScreen::OnCreationTimeout() {
379   if (actor_) {
380     actor_->ShowStatusMessage(false /* error */, l10n_util::GetStringUTF16(
381         IDS_CREATE_LOCALLY_MANAGED_USER_CREATION_CREATION_TIMEOUT_MESSAGE));
382   }
383 }
384
385 void LocallyManagedUserCreationScreen::OnLongCreationWarning() {
386   if (actor_) {
387     actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
388         IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
389   }
390 }
391
392 bool LocallyManagedUserCreationScreen::FindUserByDisplayName(
393     const base::string16& display_name,
394     std::string *out_id) const {
395   if (!existing_users_.get())
396     return false;
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) {
405         if (out_id)
406           *out_id = it.key();
407         return true;
408       }
409     }
410   }
411   return false;
412 }
413
414 // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
415 // It should be removed by issue 251179.
416
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;
426         return;
427       }
428       image_manager->SaveUserImage(UserImage::CreateAndEncode(user_photo_));
429       break;
430     case User::kProfileImageIndex:
431       NOTREACHED() << "Supervised users have no profile pictures";
432       break;
433     default:
434       DCHECK(selected_image_ >= 0 && selected_image_ < kDefaultImagesCount);
435       image_manager->SaveUserDefaultImageIndex(selected_image_);
436       break;
437   }
438   // Proceed to tutorial.
439   actor_->ShowTutorialPage();
440 }
441
442 void LocallyManagedUserCreationScreen::OnCreationSuccess() {
443   ApplyPicture();
444 }
445
446 void LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone(
447     bool is_camera_present) {
448   if (actor_)
449     actor_->SetCameraPresent(is_camera_present);
450 }
451
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();
458
459   // Stored copy, contains all necessary information.
460   existing_users_.reset(new base::DictionaryValue());
461   for (base::DictionaryValue::Iterator it(*users); !it.IsAtEnd();
462        it.Advance()) {
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());
470
471     int avatar_index = ManagedUserCreationController::kDummyAvatarIndex;
472     std::string chromeos_avatar;
473     if (local_copy->GetString(ManagedUserSyncService::kChromeOsAvatar,
474                               &chromeos_avatar) &&
475         !chromeos_avatar.empty() &&
476         ManagedUserSyncService::GetAvatarIndex(
477             chromeos_avatar, &avatar_index)) {
478       ui_copy->SetString(kAvatarURLKey, GetDefaultImageUrl(avatar_index));
479     } else {
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));
486     }
487
488     local_copy->SetBoolean(kUserExists, false);
489     ui_copy->SetBoolean(kUserExists, false);
490
491     base::string16 display_name;
492     local_copy->GetString(ManagedUserSyncService::kName, &display_name);
493
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);
504     }
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());
509
510     existing_users_->Set(it.key(), local_copy);
511     ui_users->Append(ui_copy);
512   }
513   actor_->ShowExistingManagedUsers(ui_users.get());
514 }
515
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);
528 }
529
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_)
536     ApplyPicture();
537 }
538
539 void LocallyManagedUserCreationScreen::OnDecodeImageFailed(
540     const ImageDecoder* decoder) {
541   NOTREACHED() << "Failed to decode PNG image from WebUI";
542 }
543
544 void LocallyManagedUserCreationScreen::OnImageSelected(
545     const std::string& image_type,
546     const std::string& image_url) {
547   if (image_url.empty())
548     return;
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;
555   } else {
556     NOTREACHED() << "Unexpected image type: " << image_type;
557   }
558 }
559
560 void LocallyManagedUserCreationScreen::OnImageAccepted() {
561 }
562
563 }  // namespace chromeos