Upstream version 5.34.92.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/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"
30
31 namespace chromeos {
32
33 namespace {
34
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";
43
44 const char kUserNeedPassword[] = "needPassword";
45
46 const char kAvatarURLKey[] = "avatarurl";
47 const char kRandomAvatarKey[] = "randomAvatar";
48 const char kNameOfIntroScreen[] = "intro";
49 const char kNameOfNewUserParametersScreen[] = "username";
50
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;
75   }
76 }
77
78 } // namespace
79
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);
95 }
96
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);
103 }
104
105 void LocallyManagedUserCreationScreen::PrepareToShow() {
106   if (actor_)
107     actor_->PrepareToShow();
108 }
109
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();
119   }
120
121   if (!on_error_screen_)
122     NetworkPortalDetector::Get()->AddAndFireObserver(this);
123   on_error_screen_ = false;
124 }
125
126 void LocallyManagedUserCreationScreen::OnPageSelected(const std::string& page) {
127   last_page_ = page;
128 }
129
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();
141   }
142 }
143
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));
155 }
156
157 void LocallyManagedUserCreationScreen::ShowInitialScreen() {
158   if (actor_)
159     actor_->ShowIntroPage();
160 }
161
162 void LocallyManagedUserCreationScreen::Hide() {
163   if (actor_)
164     actor_->Hide();
165   if (!on_error_screen_)
166     NetworkPortalDetector::Get()->RemoveObserver(this);
167 }
168
169 std::string LocallyManagedUserCreationScreen::GetName() const {
170   return WizardController::kLocallyManagedUserCreationScreenName;
171 }
172
173 void LocallyManagedUserCreationScreen::AbortFlow() {
174   controller_->CancelCreation();
175 }
176
177 void LocallyManagedUserCreationScreen::FinishFlow() {
178   controller_->FinishCreation();
179 }
180
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));
187
188   ExistingUserController::current_controller()->
189       Login(UserContext(manager_id,
190                         manager_password,
191                         std::string()  /* auth_code */));
192 }
193
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();
206 }
207
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;
217   }
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);
227
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;
238   }
239
240   ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
241
242   controller_->StartImport(display_name,
243                            std::string(),
244                            avatar_index,
245                            user_id,
246                            master_key);
247 }
248
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;
261   }
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);
271
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;
282   }
283
284   ManagedUserSyncService::GetAvatarIndex(avatar, &avatar_index);
285
286   controller_->StartImport(display_name,
287                            password,
288                            avatar_index,
289                            user_id,
290                            master_key);
291 }
292
293 void LocallyManagedUserCreationScreen::OnManagerLoginFailure() {
294   if (actor_)
295     actor_->ShowManagerPasswordError();
296 }
297
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();
305
306   controller_->SetManagerProfile(manager_profile);
307   if (actor_)
308     actor_->ShowUsernamePage();
309
310   last_page_ = kNameOfNewUserParametersScreen;
311
312   CommandLine* command_line = CommandLine::ForCurrentProcess();
313   if (!command_line->HasSwitch(::switches::kAllowCreateExistingManagedUsers))
314     return;
315
316   ManagedUserSyncServiceFactory::GetForProfile(manager_profile)->
317       GetManagedUsersAsync(base::Bind(
318           &LocallyManagedUserCreationScreen::OnGetManagedUsers,
319           weak_factory_.GetWeakPtr()));
320 }
321
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));
326   }
327 }
328
329 void LocallyManagedUserCreationScreen::OnActorDestroyed(
330     LocallyManagedUserCreationScreenHandler* actor) {
331   if (actor_ == actor)
332     actor_ = NULL;
333 }
334
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();
364   }
365   if (actor_)
366     actor_->ShowErrorPage(title, message, button);
367 }
368
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));
373   }
374 }
375
376 void LocallyManagedUserCreationScreen::OnLongCreationWarning() {
377   if (actor_) {
378     actor_->ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
379         IDS_PROFILES_CREATE_MANAGED_JUST_SIGNED_IN));
380   }
381 }
382
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;
399       }
400     }
401   }
402   return false;
403 }
404
405 // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
406 // It should be removed by issue 251179.
407
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;
418       }
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;
428   }
429   // Proceed to tutorial.
430   actor_->ShowTutorialPage();
431 }
432
433 void LocallyManagedUserCreationScreen::OnCreationSuccess() {
434   ApplyPicture();
435 }
436
437 void LocallyManagedUserCreationScreen::CheckCameraPresence() {
438   CameraDetector::StartPresenceCheck(
439       base::Bind(&LocallyManagedUserCreationScreen::OnCameraPresenceCheckDone,
440                  weak_factory_.GetWeakPtr()));
441 }
442
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;
450     }
451   }
452 }
453
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();
460
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());
472
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));
488     }
489
490     local_copy->SetBoolean(kUserExists, false);
491     ui_copy->SetBoolean(kUserExists, false);
492
493     base::string16 display_name;
494     local_copy->GetString(ManagedUserSyncService::kName, &display_name);
495
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);
506     }
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());
511
512     existing_users_->Set(it.key(), local_copy);
513     ui_users->Append(ui_copy);
514   }
515   actor_->ShowExistingManagedUsers(ui_users.get());
516 }
517
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);
530 }
531
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();
539 }
540
541 void LocallyManagedUserCreationScreen::OnDecodeImageFailed(
542     const ImageDecoder* decoder) {
543   NOTREACHED() << "Failed to decode PNG image from WebUI";
544 }
545
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;
559   }
560 }
561
562 void LocallyManagedUserCreationScreen::OnImageAccepted() {
563 }
564
565 }  // namespace chromeos