1// Copyright 2014 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/ui/webui/chromeos/login/supervised_user_creation_screen_handler.h"
6
7#include "ash/audio/sounds.h"
8#include "base/strings/utf_string_conversions.h"
9#include "base/values.h"
10#include "chrome/browser/chromeos/login/screens/user_selection_screen.h"
11#include "chrome/browser/chromeos/login/supervised/supervised_user_creation_flow.h"
12#include "chrome/browser/chromeos/login/users/chrome_user_manager.h"
13#include "chrome/browser/chromeos/login/users/supervised_user_manager.h"
14#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
15#include "chrome/browser/chromeos/settings/cros_settings.h"
16#include "chrome/browser/ui/webui/chromeos/login/oobe_ui.h"
17#include "chrome/common/url_constants.h"
18#include "chrome/grit/generated_resources.h"
19#include "chromeos/audio/chromeos_sounds.h"
20#include "components/user_manager/user_manager.h"
21#include "components/user_manager/user_type.h"
22#include "google_apis/gaia/gaia_auth_util.h"
23#include "grit/browser_resources.h"
24#include "net/base/data_url.h"
25#include "net/base/escape.h"
26#include "ui/base/l10n/l10n_util.h"
27#include "ui/base/resource/resource_bundle.h"
28
29const char kJsScreenPath[] = "login.SupervisedUserCreationScreen";
30
31namespace chromeos {
32
33SupervisedUserCreationScreenHandler::SupervisedUserCreationScreenHandler()
34    : BaseScreenHandler(kJsScreenPath),
35      delegate_(NULL) {
36  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
37  media::SoundsManager* manager = media::SoundsManager::Get();
38  manager->Initialize(SOUND_OBJECT_DELETE,
39                      bundle.GetRawDataResource(IDR_SOUND_OBJECT_DELETE_WAV));
40  manager->Initialize(SOUND_CAMERA_SNAP,
41                      bundle.GetRawDataResource(IDR_SOUND_CAMERA_SNAP_WAV));
42}
43
44SupervisedUserCreationScreenHandler::~SupervisedUserCreationScreenHandler() {
45  if (delegate_) {
46    delegate_->OnActorDestroyed(this);
47  }
48}
49
50void SupervisedUserCreationScreenHandler::DeclareLocalizedValues(
51    LocalizedValuesBuilder* builder) {
52  builder->Add(
53      "supervisedUserCreationFlowRetryButtonTitle",
54      IDS_CREATE_SUPERVISED_USER_CREATION_ERROR_RETRY_BUTTON_TITLE);
55  builder->Add(
56      "supervisedUserCreationFlowCancelButtonTitle",
57      IDS_CREATE_SUPERVISED_USER_CREATION_ERROR_CANCEL_BUTTON_TITLE);
58  builder->Add(
59      "supervisedUserCreationFlowGotitButtonTitle",
60       IDS_CREATE_SUPERVISED_USER_CREATION_GOT_IT_BUTTON_TITLE);
61
62  builder->Add("createSupervisedUserIntroTextTitle",
63               IDS_CREATE_SUPERVISED_INTRO_TEXT_TITLE);
64  builder->Add("createSupervisedUserIntroAlternateText",
65               IDS_CREATE_SUPERVISED_INTRO_ALTERNATE_TEXT);
66  builder->Add("createSupervisedUserIntroText1",
67               IDS_CREATE_SUPERVISED_INTRO_TEXT_1);
68  builder->Add("createSupervisedUserIntroManagerItem1",
69               IDS_CREATE_SUPERVISED_INTRO_MANAGER_ITEM_1);
70  builder->Add("createSupervisedUserIntroManagerItem2",
71               IDS_CREATE_SUPERVISED_INTRO_MANAGER_ITEM_2);
72  builder->Add("createSupervisedUserIntroManagerItem3",
73               IDS_CREATE_SUPERVISED_INTRO_MANAGER_ITEM_3);
74  builder->Add("createSupervisedUserIntroText2",
75               IDS_CREATE_SUPERVISED_INTRO_TEXT_2);
76  builder->AddF("createSupervisedUserIntroText3",
77               IDS_CREATE_SUPERVISED_INTRO_TEXT_3,
78               base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
79
80  builder->Add("createSupervisedUserPickManagerTitle",
81               IDS_CREATE_SUPERVISED_USER_CREATE_PICK_MANAGER_TITLE);
82  builder->AddF("createSupervisedUserPickManagerTitleExplanation",
83               IDS_CREATE_SUPERVISED_USER_CREATE_PICK_MANAGER_EXPLANATION,
84               base::UTF8ToUTF16(chrome::kSupervisedUserManagementDisplayURL));
85  builder->Add("createSupervisedUserManagerPasswordHint",
86               IDS_CREATE_SUPERVISED_USER_CREATE_MANAGER_PASSWORD_HINT);
87  builder->Add("createSupervisedUserWrongManagerPasswordText",
88               IDS_CREATE_SUPERVISED_USER_MANAGER_PASSWORD_ERROR);
89
90  builder->Add("createSupervisedUserNameTitle",
91               IDS_CREATE_SUPERVISED_USER_CREATE_ACCOUNT_NAME_TITLE);
92  builder->Add("createSupervisedUserNameAccessibleTitle",
93               IDS_CREATE_SUPERVISED_USER_SETUP_ACCESSIBLE_TITLE);
94  builder->Add("createSupervisedUserNameExplanation",
95               IDS_CREATE_SUPERVISED_USER_CREATE_ACCOUNT_NAME_EXPLANATION);
96  builder->Add("createSupervisedUserNameHint",
97               IDS_CREATE_SUPERVISED_USER_CREATE_ACCOUNT_NAME_HINT);
98  builder->Add("createSupervisedUserPasswordTitle",
99               IDS_CREATE_SUPERVISED_USER_CREATE_PASSWORD_TITLE);
100  builder->Add("createSupervisedUserPasswordExplanation",
101               IDS_CREATE_SUPERVISED_USER_CREATE_PASSWORD_EXPLANATION);
102  builder->Add("createSupervisedUserPasswordHint",
103               IDS_CREATE_SUPERVISED_USER_CREATE_PASSWORD_HINT);
104  builder->Add("createSupervisedUserPasswordConfirmHint",
105               IDS_CREATE_SUPERVISED_USER_CREATE_PASSWORD_CONFIRM_HINT);
106  builder->Add("supervisedUserCreationFlowProceedButtonTitle",
107               IDS_CREATE_SUPERVISED_USER_CREATE_CONTINUE_BUTTON_TEXT);
108  builder->Add("supervisedUserCreationFlowStartButtonTitle",
109               IDS_CREATE_SUPERVISED_USER_CREATE_START_BUTTON_TEXT);
110  builder->Add("supervisedUserCreationFlowPrevButtonTitle",
111               IDS_CREATE_SUPERVISED_USER_CREATE_PREVIOUS_BUTTON_TEXT);
112  builder->Add("supervisedUserCreationFlowNextButtonTitle",
113               IDS_CREATE_SUPERVISED_USER_CREATE_NEXT_BUTTON_TEXT);
114  builder->Add("supervisedUserCreationFlowHandleErrorButtonTitle",
115               IDS_CREATE_SUPERVISED_USER_CREATE_HANDLE_ERROR_BUTTON_TEXT);
116  builder->Add("createSupervisedUserPasswordMismatchError",
117               IDS_CREATE_SUPERVISED_USER_CREATE_PASSWORD_MISMATCH_ERROR);
118
119  builder->Add("createSupervisedUserCreatedText1",
120               IDS_CREATE_SUPERVISED_USER_CREATED_1_TEXT_1);
121  builder->Add("createSupervisedUserCreatedText2",
122               IDS_CREATE_SUPERVISED_USER_CREATED_1_TEXT_2);
123  builder->Add("createSupervisedUserCreatedText3",
124               IDS_CREATE_SUPERVISED_USER_CREATED_1_TEXT_3);
125
126  builder->Add("importExistingSupervisedUserTitle",
127               IDS_IMPORT_EXISTING_SUPERVISED_USER_TITLE);
128  builder->Add("importExistingSupervisedUserText",
129               IDS_IMPORT_EXISTING_SUPERVISED_USER_TEXT);
130  builder->Add("supervisedUserCreationFlowImportButtonTitle",
131               IDS_IMPORT_EXISTING_SUPERVISED_USER_OK);
132  builder->Add("importSupervisedUserLink",
133               IDS_PROFILES_IMPORT_EXISTING_SUPERVISED_USER_LINK);
134  builder->Add("createSupervisedUserLink",
135               IDS_CREATE_NEW_USER_LINK);
136  builder->Add("importBubbleText", IDS_SUPERVISED_USER_IMPORT_BUBBLE_TEXT);
137  builder->Add("importUserExists", IDS_SUPERVISED_USER_IMPORT_USER_EXIST);
138  builder->Add("importUsernameExists",
139               IDS_SUPERVISED_USER_IMPORT_USERNAME_EXIST);
140
141  builder->Add("managementURL", chrome::kSupervisedUserManagementDisplayURL);
142
143  // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
144  // It should be removed by issue 251179.
145  builder->Add("takePhoto", IDS_OPTIONS_CHANGE_PICTURE_TAKE_PHOTO);
146  builder->Add("discardPhoto", IDS_OPTIONS_CHANGE_PICTURE_DISCARD_PHOTO);
147  builder->Add("flipPhoto", IDS_OPTIONS_CHANGE_PICTURE_FLIP_PHOTO);
148  builder->Add("photoFlippedAccessibleText",
149               IDS_OPTIONS_PHOTO_FLIP_ACCESSIBLE_TEXT);
150  builder->Add("photoFlippedBackAccessibleText",
151               IDS_OPTIONS_PHOTO_FLIPBACK_ACCESSIBLE_TEXT);
152  builder->Add("photoCaptureAccessibleText",
153               IDS_OPTIONS_PHOTO_CAPTURE_ACCESSIBLE_TEXT);
154  builder->Add("photoDiscardAccessibleText",
155               IDS_OPTIONS_PHOTO_DISCARD_ACCESSIBLE_TEXT);
156}
157
158void SupervisedUserCreationScreenHandler::Initialize() {}
159
160void SupervisedUserCreationScreenHandler::RegisterMessages() {
161  AddCallback("finishLocalSupervisedUserCreation",
162              &SupervisedUserCreationScreenHandler::
163                  HandleFinishLocalSupervisedUserCreation);
164  AddCallback("abortLocalSupervisedUserCreation",
165              &SupervisedUserCreationScreenHandler::
166                  HandleAbortLocalSupervisedUserCreation);
167  AddCallback("checkSupervisedUserName",
168              &SupervisedUserCreationScreenHandler::
169                  HandleCheckSupervisedUserName);
170  AddCallback("authenticateManagerInSupervisedUserCreationFlow",
171              &SupervisedUserCreationScreenHandler::
172                  HandleAuthenticateManager);
173  AddCallback("specifySupervisedUserCreationFlowUserData",
174              &SupervisedUserCreationScreenHandler::
175                  HandleCreateSupervisedUser);
176  AddCallback("managerSelectedOnSupervisedUserCreationFlow",
177              &SupervisedUserCreationScreenHandler::
178                  HandleManagerSelected);
179  AddCallback("userSelectedForImportInSupervisedUserCreationFlow",
180              &SupervisedUserCreationScreenHandler::
181                  HandleImportUserSelected);
182  AddCallback("importSupervisedUser",
183              &SupervisedUserCreationScreenHandler::
184                  HandleImportSupervisedUser);
185  AddCallback("importSupervisedUserWithPassword",
186              &SupervisedUserCreationScreenHandler::
187                  HandleImportSupervisedUserWithPassword);
188
189
190  // TODO(antrim) : this is an explicit code duplications with UserImageScreen.
191  // It should be removed by issue 251179.
192  AddCallback("supervisedUserGetImages",
193              &SupervisedUserCreationScreenHandler::HandleGetImages);
194
195  AddCallback("supervisedUserPhotoTaken",
196              &SupervisedUserCreationScreenHandler::HandlePhotoTaken);
197  AddCallback("supervisedUserTakePhoto",
198              &SupervisedUserCreationScreenHandler::HandleTakePhoto);
199  AddCallback("supervisedUserDiscardPhoto",
200              &SupervisedUserCreationScreenHandler::HandleDiscardPhoto);
201  AddCallback("supervisedUserSelectImage",
202              &SupervisedUserCreationScreenHandler::HandleSelectImage);
203  AddCallback("currentSupervisedUserPage",
204              &SupervisedUserCreationScreenHandler::
205                  HandleCurrentSupervisedUserPage);
206}
207
208void SupervisedUserCreationScreenHandler::PrepareToShow() {}
209
210void SupervisedUserCreationScreenHandler::Show() {
211  scoped_ptr<base::DictionaryValue> data(new base::DictionaryValue());
212  scoped_ptr<base::ListValue> users_list(new base::ListValue());
213  const user_manager::UserList& users =
214      user_manager::UserManager::Get()->GetUsers();
215  std::string owner;
216  chromeos::CrosSettings::Get()->GetString(chromeos::kDeviceOwner, &owner);
217
218  for (user_manager::UserList::const_iterator it = users.begin();
219       it != users.end();
220       ++it) {
221    if ((*it)->GetType() != user_manager::USER_TYPE_REGULAR)
222      continue;
223    bool is_owner = ((*it)->email() == owner);
224    base::DictionaryValue* user_dict = new base::DictionaryValue();
225    UserSelectionScreen::FillUserDictionary(
226        *it,
227        is_owner,
228        false, /* is_signin_to_add */
229        ScreenlockBridge::LockHandler::OFFLINE_PASSWORD,
230        NULL, /* public_session_recommended_locales */
231        user_dict);
232    users_list->Append(user_dict);
233  }
234  data->Set("managers", users_list.release());
235  ShowScreen(OobeUI::kScreenSupervisedUserCreationFlow, data.get());
236
237  if (!delegate_)
238    return;
239}
240
241void SupervisedUserCreationScreenHandler::Hide() {
242}
243
244void SupervisedUserCreationScreenHandler::ShowIntroPage() {
245  CallJS("showIntroPage");
246}
247
248void SupervisedUserCreationScreenHandler::ShowManagerPasswordError() {
249  CallJS("showManagerPasswordError");
250}
251
252void SupervisedUserCreationScreenHandler::ShowStatusMessage(
253    bool is_progress,
254    const base::string16& message) {
255  if (is_progress)
256    CallJS("showProgress", message);
257  else
258    CallJS("showStatusError", message);
259}
260
261void SupervisedUserCreationScreenHandler::ShowUsernamePage() {
262  CallJS("showUsernamePage");
263}
264
265void SupervisedUserCreationScreenHandler::ShowTutorialPage() {
266  CallJS("showTutorialPage");
267}
268
269void SupervisedUserCreationScreenHandler::ShowErrorPage(
270    const base::string16& title,
271    const base::string16& message,
272    const base::string16& button_text) {
273  CallJS("showErrorPage", title, message, button_text);
274}
275
276void SupervisedUserCreationScreenHandler::SetDelegate(Delegate* delegate) {
277  delegate_ = delegate;
278}
279
280void SupervisedUserCreationScreenHandler::
281    HandleFinishLocalSupervisedUserCreation() {
282  delegate_->FinishFlow();
283}
284
285void SupervisedUserCreationScreenHandler::
286    HandleAbortLocalSupervisedUserCreation() {
287  delegate_->AbortFlow();
288}
289
290void SupervisedUserCreationScreenHandler::HandleManagerSelected(
291    const std::string& manager_id) {
292  if (!delegate_)
293    return;
294  WallpaperManager::Get()->SetUserWallpaperNow(manager_id);
295}
296
297void SupervisedUserCreationScreenHandler::HandleImportUserSelected(
298    const std::string& user_id) {
299  if (!delegate_)
300    return;
301}
302
303void SupervisedUserCreationScreenHandler::HandleCheckSupervisedUserName(
304    const base::string16& name) {
305  std::string user_id;
306  if (NULL !=
307      ChromeUserManager::Get()->GetSupervisedUserManager()->FindByDisplayName(
308          base::CollapseWhitespace(name, true))) {
309    CallJS("supervisedUserNameError", name,
310           l10n_util::GetStringUTF16(
311               IDS_CREATE_SUPERVISED_USER_CREATE_USERNAME_ALREADY_EXISTS));
312  } else if (net::EscapeForHTML(name) != name) {
313    CallJS("supervisedUserNameError", name,
314           l10n_util::GetStringUTF16(
315               IDS_CREATE_SUPERVISED_USER_CREATE_ILLEGAL_USERNAME));
316  } else if (delegate_ && delegate_->FindUserByDisplayName(
317                 base::CollapseWhitespace(name, true), &user_id)) {
318    CallJS("supervisedUserSuggestImport", name, user_id);
319  } else {
320    CallJS("supervisedUserNameOk", name);
321  }
322}
323
324void SupervisedUserCreationScreenHandler::HandleCreateSupervisedUser(
325    const base::string16& new_raw_user_name,
326    const std::string& new_user_password) {
327  if (!delegate_)
328    return;
329  const base::string16 new_user_name =
330      base::CollapseWhitespace(new_raw_user_name, true);
331  if (NULL !=
332      ChromeUserManager::Get()->GetSupervisedUserManager()->FindByDisplayName(
333          new_user_name)) {
334    CallJS("supervisedUserNameError", new_user_name,
335           l10n_util::GetStringFUTF16(
336               IDS_CREATE_SUPERVISED_USER_CREATE_USERNAME_ALREADY_EXISTS,
337               new_user_name));
338    return;
339  }
340  if (net::EscapeForHTML(new_user_name) != new_user_name) {
341    CallJS("supervisedUserNameError", new_user_name,
342           l10n_util::GetStringUTF16(
343               IDS_CREATE_SUPERVISED_USER_CREATE_ILLEGAL_USERNAME));
344    return;
345  }
346
347  if (new_user_password.length() == 0) {
348    CallJS("showPasswordError",
349           l10n_util::GetStringUTF16(
350               IDS_CREATE_SUPERVISED_USER_CREATE_PASSWORD_TOO_SHORT));
351    return;
352  }
353
354  ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
355      IDS_CREATE_SUPERVISED_USER_CREATION_CREATION_PROGRESS_MESSAGE));
356
357  delegate_->CreateSupervisedUser(new_user_name, new_user_password);
358}
359
360void SupervisedUserCreationScreenHandler::HandleImportSupervisedUser(
361    const std::string& user_id) {
362  if (!delegate_)
363    return;
364
365  ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
366      IDS_CREATE_SUPERVISED_USER_CREATION_CREATION_PROGRESS_MESSAGE));
367
368  delegate_->ImportSupervisedUser(user_id);
369}
370
371void SupervisedUserCreationScreenHandler::
372    HandleImportSupervisedUserWithPassword(
373        const std::string& user_id,
374        const std::string& password) {
375  if (!delegate_)
376    return;
377
378  ShowStatusMessage(true /* progress */, l10n_util::GetStringUTF16(
379      IDS_CREATE_SUPERVISED_USER_CREATION_CREATION_PROGRESS_MESSAGE));
380
381  delegate_->ImportSupervisedUserWithPassword(user_id, password);
382}
383
384void SupervisedUserCreationScreenHandler::HandleAuthenticateManager(
385    const std::string& raw_manager_username,
386    const std::string& manager_password) {
387  const std::string manager_username =
388      gaia::SanitizeEmail(raw_manager_username);
389  delegate_->AuthenticateManager(manager_username, manager_password);
390}
391
392// TODO(antrim) : this is an explicit code duplications with UserImageScreen.
393// It should be removed by issue 251179.
394void SupervisedUserCreationScreenHandler::HandleGetImages() {
395  base::ListValue image_urls;
396  for (int i = user_manager::kFirstDefaultImageIndex;
397       i < user_manager::kDefaultImagesCount;
398       ++i) {
399    scoped_ptr<base::DictionaryValue> image_data(new base::DictionaryValue);
400    image_data->SetString("url", user_manager::GetDefaultImageUrl(i));
401    image_data->SetString(
402        "author",
403        l10n_util::GetStringUTF16(user_manager::kDefaultImageAuthorIDs[i]));
404    image_data->SetString(
405        "website",
406        l10n_util::GetStringUTF16(user_manager::kDefaultImageWebsiteIDs[i]));
407    image_data->SetString("title", user_manager::GetDefaultImageDescription(i));
408    image_urls.Append(image_data.release());
409  }
410  CallJS("setDefaultImages", image_urls);
411}
412
413void SupervisedUserCreationScreenHandler::HandlePhotoTaken
414    (const std::string& image_url) {
415  std::string mime_type, charset, raw_data;
416  if (!net::DataURL::Parse(GURL(image_url), &mime_type, &charset, &raw_data))
417    NOTREACHED();
418  DCHECK_EQ("image/png", mime_type);
419
420  if (delegate_)
421    delegate_->OnPhotoTaken(raw_data);
422}
423
424void SupervisedUserCreationScreenHandler::HandleTakePhoto() {
425#if !defined(USE_ATHENA)
426  // crbug.com/408733
427  ash::PlaySystemSoundIfSpokenFeedback(SOUND_CAMERA_SNAP);
428#endif
429}
430
431void SupervisedUserCreationScreenHandler::HandleDiscardPhoto() {
432#if !defined(USE_ATHENA)
433  ash::PlaySystemSoundIfSpokenFeedback(SOUND_OBJECT_DELETE);
434#endif
435}
436
437void SupervisedUserCreationScreenHandler::HandleSelectImage(
438    const std::string& image_url,
439    const std::string& image_type) {
440  if (delegate_)
441    delegate_->OnImageSelected(image_type, image_url);
442}
443
444void SupervisedUserCreationScreenHandler::HandleCurrentSupervisedUserPage(
445    const std::string& page) {
446  if (delegate_)
447    delegate_->OnPageSelected(page);
448}
449
450void SupervisedUserCreationScreenHandler::ShowPage(
451    const std::string& page) {
452  CallJS("showPage", page);
453}
454
455void SupervisedUserCreationScreenHandler::SetCameraPresent(bool present) {
456  CallJS("setCameraPresent", present);
457}
458
459void SupervisedUserCreationScreenHandler::ShowExistingSupervisedUsers(
460    const base::ListValue* users) {
461  CallJS("setExistingSupervisedUsers", *users);
462}
463
464}  // namespace chromeos
465