Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(350)

Side by Side Diff: chrome/browser/resources/chromeos/login/screen_locally_managed_user_creation.js

Issue 403343002: Rename "managed (mode|user)" to "supervised user" (part 8) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 /**
6 * @fileoverview Locally managed user creation flow screen.
7 */
8
9 login.createScreen('LocallyManagedUserCreationScreen',
10 'managed-user-creation', function() {
11 var MAX_NAME_LENGTH = 50;
12 var UserImagesGrid = options.UserImagesGrid;
13 var ButtonImages = UserImagesGrid.ButtonImages;
14
15 var ManagerPod = cr.ui.define(function() {
16 var node = $('managed-user-creation-manager-template').cloneNode(true);
17 node.removeAttribute('id');
18 node.removeAttribute('hidden');
19 return node;
20 });
21
22 ManagerPod.userImageSalt_ = {};
23
24 /**
25 * UI element for displaying single account in list of possible managers for
26 * new locally managed user.
27 * @type {Object}
28 */
29 ManagerPod.prototype = {
30 __proto__: HTMLDivElement.prototype,
31
32 /** @override */
33 decorate: function() {
34 // Mousedown has to be used instead of click to be able to prevent 'focus'
35 // event later.
36 this.addEventListener('mousedown',
37 this.handleMouseDown_.bind(this));
38 var screen = $('managed-user-creation');
39 var managerPod = this;
40 var managerPodList = screen.managerList_;
41 var hideManagerPasswordError = function(element) {
42 managerPod.passwordElement.classList.remove('password-error');
43 $('bubble').hide();
44 };
45
46 screen.configureTextInput(
47 this.passwordElement,
48 screen.updateNextButtonForManager_.bind(screen),
49 screen.validIfNotEmpty_.bind(screen),
50 function(element) {
51 screen.getScreenButton('next').focus();
52 },
53 hideManagerPasswordError);
54
55 this.passwordElement.addEventListener('keydown', function(e) {
56 switch (e.keyIdentifier) {
57 case 'Up':
58 managerPodList.selectNextPod(-1);
59 e.stopPropagation();
60 break;
61 case 'Down':
62 managerPodList.selectNextPod(+1);
63 e.stopPropagation();
64 break;
65 }
66 });
67 },
68
69 /**
70 * Updates UI elements from user data.
71 */
72 update: function() {
73 this.imageElement.src = 'chrome://userimage/' + this.user.username +
74 '?id=' + ManagerPod.userImageSalt_[this.user.username];
75
76 this.nameElement.textContent = this.user.displayName;
77 this.emailElement.textContent = this.user.emailAddress;
78 },
79
80 showPasswordError: function() {
81 this.passwordElement.classList.add('password-error');
82 $('bubble').showTextForElement(
83 this.passwordElement,
84 loadTimeData.getString('createManagedUserWrongManagerPasswordText'),
85 cr.ui.Bubble.Attachment.BOTTOM,
86 24, 4);
87 },
88
89 /**
90 * Brings focus to password field.
91 */
92 focusInput: function() {
93 this.passwordElement.focus();
94 },
95
96 /**
97 * Gets image element.
98 * @type {!HTMLImageElement}
99 */
100 get imageElement() {
101 return this.querySelector('.managed-user-creation-manager-image');
102 },
103
104 /**
105 * Gets name element.
106 * @type {!HTMLDivElement}
107 */
108 get nameElement() {
109 return this.querySelector('.managed-user-creation-manager-name');
110 },
111
112 /**
113 * Gets e-mail element.
114 * @type {!HTMLDivElement}
115 */
116 get emailElement() {
117 return this.querySelector('.managed-user-creation-manager-email');
118 },
119
120 /**
121 * Gets password element.
122 * @type {!HTMLDivElement}
123 */
124 get passwordElement() {
125 return this.querySelector('.managed-user-creation-manager-password');
126 },
127
128 /**
129 * Gets password enclosing block.
130 * @type {!HTMLDivElement}
131 */
132 get passwordBlock() {
133 return this.querySelector('.password-block');
134 },
135
136 /** @override */
137 handleMouseDown_: function(e) {
138 this.parentNode.selectPod(this);
139 // Prevent default so that we don't trigger 'focus' event.
140 e.preventDefault();
141 },
142
143 /**
144 * The user that this pod represents.
145 * @type {!Object}
146 */
147 user_: undefined,
148 get user() {
149 return this.user_;
150 },
151 set user(userDict) {
152 this.user_ = userDict;
153 this.update();
154 },
155 };
156
157 var ManagerPodList = cr.ui.define('div');
158
159 /**
160 * UI element for selecting manager account for new managed user.
161 * @type {Object}
162 */
163 ManagerPodList.prototype = {
164 __proto__: HTMLDivElement.prototype,
165
166 selectedPod_: null,
167
168 /** @override */
169 decorate: function() {
170 },
171
172 /**
173 * Returns all the pods in this pod list.
174 * @type {NodeList}
175 */
176 get pods() {
177 return this.children;
178 },
179
180 addPod: function(manager) {
181 var managerPod = new ManagerPod({user: manager});
182 this.appendChild(managerPod);
183 managerPod.update();
184 },
185
186 clearPods: function() {
187 this.innerHTML = '';
188 this.selectedPod_ = null;
189 },
190
191 selectPod: function(podToSelect) {
192 if ((this.selectedPod_ == podToSelect) && !!podToSelect) {
193 podToSelect.focusInput();
194 return;
195 }
196 this.selectedPod_ = podToSelect;
197 for (var i = 0, pod; pod = this.pods[i]; ++i) {
198 if (pod != podToSelect) {
199 pod.classList.remove('focused');
200 pod.passwordElement.value = '';
201 pod.passwordBlock.hidden = true;
202 }
203 }
204 if (!podToSelect)
205 return;
206 podToSelect.classList.add('focused');
207 podToSelect.passwordBlock.hidden = false;
208 podToSelect.passwordElement.value = '';
209 podToSelect.focusInput();
210 chrome.send('managerSelectedOnLocallyManagedUserCreationFlow',
211 [podToSelect.user.username]);
212 },
213
214 /**
215 * Select pod next to currently selected one in given |direction|.
216 * @param {integer} direction - +1 for selecting pod below current, -1 for
217 * selecting pod above current.
218 * @type {boolean} returns if selected pod has changed.
219 */
220 selectNextPod: function(direction) {
221 if (!this.selectedPod_)
222 return false;
223 var index = -1;
224 for (var i = 0, pod; pod = this.pods[i]; ++i) {
225 if (pod == this.selectedPod_) {
226 index = i;
227 break;
228 }
229 }
230 if (-1 == index)
231 return false;
232 index = index + direction;
233 if (index < 0 || index >= this.pods.length)
234 return false;
235 this.selectPod(this.pods[index]);
236 return true;
237 }
238 };
239
240 var ImportPod = cr.ui.define(function() {
241 var node = $('managed-user-creation-import-template').cloneNode(true);
242 node.removeAttribute('id');
243 node.removeAttribute('hidden');
244 return node;
245 });
246
247 /**
248 * UI element for displaying single supervised user in list of possible users
249 * for importing existing users.
250 * @type {Object}
251 */
252 ImportPod.prototype = {
253 __proto__: HTMLDivElement.prototype,
254
255 /** @override */
256 decorate: function() {
257 // Mousedown has to be used instead of click to be able to prevent 'focus'
258 // event later.
259 this.addEventListener('mousedown', this.handleMouseDown_.bind(this));
260 var screen = $('managed-user-creation');
261 var importList = screen.importList_;
262 },
263
264 /**
265 * Updates UI elements from user data.
266 */
267 update: function() {
268 this.imageElement.src = this.user.avatarurl;
269 this.nameElement.textContent = this.user.name;
270 if (this.user.exists) {
271 if (this.user.conflict == 'imported') {
272 this.nameElement.textContent =
273 loadTimeData.getStringF('importUserExists', this.user.name);
274 } else {
275 this.nameElement.textContent =
276 loadTimeData.getStringF('importUsernameExists', this.user.name);
277 }
278 }
279 this.classList.toggle('imported', this.user.exists);
280 },
281
282 /**
283 * Gets image element.
284 * @type {!HTMLImageElement}
285 */
286 get imageElement() {
287 return this.querySelector('.import-pod-image');
288 },
289
290 /**
291 * Gets name element.
292 * @type {!HTMLDivElement}
293 */
294 get nameElement() {
295 return this.querySelector('.import-pod-name');
296 },
297
298 /** @override */
299 handleMouseDown_: function(e) {
300 this.parentNode.selectPod(this);
301 // Prevent default so that we don't trigger 'focus' event.
302 e.preventDefault();
303 },
304
305 /**
306 * The user that this pod represents.
307 * @type {Object}
308 */
309 user_: undefined,
310
311 get user() {
312 return this.user_;
313 },
314
315 set user(userDict) {
316 this.user_ = userDict;
317 this.update();
318 },
319 };
320
321 var ImportPodList = cr.ui.define('div');
322
323 /**
324 * UI element for selecting existing supervised user for import.
325 * @type {Object}
326 */
327 ImportPodList.prototype = {
328 __proto__: HTMLDivElement.prototype,
329
330 selectedPod_: null,
331
332 /** @override */
333 decorate: function() {
334 this.setAttribute('tabIndex', 0);
335 this.classList.add('nofocus');
336 var importList = this;
337 var screen = $('managed-user-creation');
338
339 this.addEventListener('focus', function(e) {
340 if (importList.selectedPod_ == null) {
341 if (importList.pods.length > 0)
342 importList.selectPod(importList.pods[0]);
343 }
344 });
345
346 this.addEventListener('keydown', function(e) {
347 switch (e.keyIdentifier) {
348 case 'Up':
349 importList.selectNextPod(-1);
350 e.stopPropagation();
351 break;
352 case 'Enter':
353 if (importList.selectedPod_ != null)
354 screen.importSupervisedUser_();
355 e.stopPropagation();
356 break;
357 case 'Down':
358 importList.selectNextPod(+1);
359 e.stopPropagation();
360 break;
361 }
362 });
363 },
364
365 /**
366 * Returns all the pods in this pod list.
367 * @type {NodeList}
368 */
369 get pods() {
370 return this.children;
371 },
372
373 /**
374 * Returns selected pod.
375 * @type {Node}
376 */
377 get selectedPod() {
378 return this.selectedPod_;
379 },
380
381 addPod: function(user) {
382 var importPod = new ImportPod({user: user});
383 this.appendChild(importPod);
384 importPod.update();
385 },
386
387 clearPods: function() {
388 this.innerHTML = '';
389 this.selectedPod_ = null;
390 },
391
392 scrollIntoView: function(pod) {
393 scroller = this.parentNode;
394 var itemHeight = pod.getBoundingClientRect().height;
395 var scrollTop = scroller.scrollTop;
396 var top = pod.offsetTop - scroller.offsetTop;
397 var clientHeight = scroller.clientHeight;
398
399 var self = scroller;
400
401 // Function to adjust the tops of viewport and row.
402 function scrollToAdjustTop() {
403 self.scrollTop = top;
404 return true;
405 };
406 // Function to adjust the bottoms of viewport and row.
407 function scrollToAdjustBottom() {
408 var cs = getComputedStyle(self);
409 var paddingY = parseInt(cs.paddingTop, 10) +
410 parseInt(cs.paddingBottom, 10);
411
412 if (top + itemHeight > scrollTop + clientHeight - paddingY) {
413 self.scrollTop = top + itemHeight - clientHeight + paddingY;
414 return true;
415 }
416 return false;
417 };
418
419 // Check if the entire of given indexed row can be shown in the viewport.
420 if (itemHeight <= clientHeight) {
421 if (top < scrollTop)
422 return scrollToAdjustTop();
423 if (scrollTop + clientHeight < top + itemHeight)
424 return scrollToAdjustBottom();
425 } else {
426 if (scrollTop < top)
427 return scrollToAdjustTop();
428 if (top + itemHeight < scrollTop + clientHeight)
429 return scrollToAdjustBottom();
430 }
431 return false;
432 },
433
434 /**
435 * @param {Element} podToSelect - pod to select, can be null.
436 */
437 selectPod: function(podToSelect) {
438 if ((this.selectedPod_ == podToSelect) && !!podToSelect) {
439 return;
440 }
441 this.selectedPod_ = podToSelect;
442 for (var i = 0; i < this.pods.length; i++) {
443 var pod = this.pods[i];
444 if (pod != podToSelect)
445 pod.classList.remove('focused');
446 }
447 if (!podToSelect)
448 return;
449 podToSelect.classList.add('focused');
450 podToSelect.focus();
451 var screen = $('managed-user-creation');
452 if (!this.selectedPod_) {
453 screen.getScreenButton('import').disabled = true;
454 } else {
455 screen.getScreenButton('import').disabled =
456 this.selectedPod_.user.exists;
457 if (!this.selectedPod_.user.exists) {
458 chrome.send('userSelectedForImportInManagedUserCreationFlow',
459 [podToSelect.user.id]);
460 }
461 }
462 },
463
464 selectNextPod: function(direction) {
465 if (!this.selectedPod_)
466 return false;
467 var index = -1;
468 for (var i = 0, pod; pod = this.pods[i]; ++i) {
469 if (pod == this.selectedPod_) {
470 index = i;
471 break;
472 }
473 }
474 if (-1 == index)
475 return false;
476 index = index + direction;
477 if (index < 0 || index >= this.pods.length)
478 return false;
479 this.selectPod(this.pods[index]);
480 return true;
481 },
482
483 selectUser: function(user_id) {
484 for (var i = 0, pod; pod = this.pods[i]; ++i) {
485 if (pod.user.id == user_id) {
486 this.selectPod(pod);
487 this.scrollIntoView(pod);
488 break;
489 }
490 }
491 },
492 };
493
494 return {
495 EXTERNAL_API: [
496 'loadManagers',
497 'managedUserSuggestImport',
498 'managedUserNameError',
499 'managedUserNameOk',
500 'showErrorPage',
501 'showIntroPage',
502 'showManagerPage',
503 'showManagerPasswordError',
504 'showPasswordError',
505 'showProgress',
506 'showStatusError',
507 'showTutorialPage',
508 'showUsernamePage',
509 'showPage',
510 'setDefaultImages',
511 'setCameraPresent',
512 'setExistingManagedUsers',
513 ],
514
515 lastVerifiedName_: null,
516 lastIncorrectUserName_: null,
517 managerList_: null,
518 importList_: null,
519
520 currentPage_: null,
521 imagesRequested_: false,
522
523 // Contains data that can be auto-shared with handler.
524 context_: {},
525
526 /** @override */
527 decorate: function() {
528 this.managerList_ = new ManagerPodList();
529 $('managed-user-creation-managers-pane').appendChild(this.managerList_);
530
531 this.importList_ = new ImportPodList();
532 $('managed-user-creation-import-pane').appendChild(this.importList_);
533
534 var userNameField = $('managed-user-creation-name');
535 var passwordField = $('managed-user-creation-password');
536 var password2Field = $('managed-user-creation-password-confirm');
537
538 var creationScreen = this;
539
540 var hideUserPasswordError = function(element) {
541 $('bubble').hide();
542 $('managed-user-creation-password').classList.remove('password-error');
543 };
544
545 this.configureTextInput(userNameField,
546 this.checkUserName_.bind(this),
547 this.validIfNotEmpty_.bind(this),
548 function(element) {
549 passwordField.focus();
550 },
551 this.clearUserNameError_.bind(this));
552 this.configureTextInput(passwordField,
553 this.updateNextButtonForUser_.bind(this),
554 this.validIfNotEmpty_.bind(this),
555 function(element) {
556 password2Field.focus();
557 },
558 hideUserPasswordError);
559 this.configureTextInput(password2Field,
560 this.updateNextButtonForUser_.bind(this),
561 this.validIfNotEmpty_.bind(this),
562 function(element) {
563 creationScreen.getScreenButton('next').focus();
564 },
565 hideUserPasswordError);
566
567 this.getScreenButton('error').addEventListener('click', function(e) {
568 creationScreen.handleErrorButtonPressed_();
569 e.stopPropagation();
570 });
571
572 /*
573 TODO(antrim) : this is an explicit code duplications with UserImageScreen.
574 It should be removed by issue 251179.
575 */
576 var imageGrid = this.getScreenElement('image-grid');
577 UserImagesGrid.decorate(imageGrid);
578
579 // Preview image will track the selected item's URL.
580 var previewElement = this.getScreenElement('image-preview');
581 previewElement.oncontextmenu = function(e) { e.preventDefault(); };
582
583 imageGrid.previewElement = previewElement;
584 imageGrid.selectionType = 'default';
585 imageGrid.flipPhotoElement = this.getScreenElement('flip-photo');
586
587 imageGrid.addEventListener('activate',
588 this.handleActivate_.bind(this));
589 imageGrid.addEventListener('select',
590 this.handleSelect_.bind(this));
591 imageGrid.addEventListener('phototaken',
592 this.handlePhotoTaken_.bind(this));
593 imageGrid.addEventListener('photoupdated',
594 this.handlePhotoUpdated_.bind(this));
595 // Set the title for camera item in the grid.
596 imageGrid.setCameraTitles(
597 loadTimeData.getString('takePhoto'),
598 loadTimeData.getString('photoFromCamera'));
599
600 this.getScreenElement('take-photo').addEventListener(
601 'click', this.handleTakePhoto_.bind(this));
602 this.getScreenElement('discard-photo').addEventListener(
603 'click', this.handleDiscardPhoto_.bind(this));
604
605 // Toggle 'animation' class for the duration of WebKit transition.
606 this.getScreenElement('flip-photo').addEventListener(
607 'click', this.handleFlipPhoto_.bind(this));
608 this.getScreenElement('image-stream-crop').addEventListener(
609 'webkitTransitionEnd', function(e) {
610 previewElement.classList.remove('animation');
611 });
612 this.getScreenElement('image-preview-img').addEventListener(
613 'webkitTransitionEnd', function(e) {
614 previewElement.classList.remove('animation');
615 });
616 },
617
618 buttonIds: [],
619
620 /**
621 * Creates button for adding to controls.
622 * @param {string} buttonId -- id for button, have to be unique within
623 * screen. Actual id will be prefixed with screen name and appended with
624 * '-button'. Use getScreenButton(buttonId) to find it later.
625 * @param {string} i18nPrefix -- screen prefix for i18n values.
626 * @param {function} callback -- will be called on button press with
627 * buttonId parameter.
628 * @param {array} pages -- list of pages where this button should be
629 * displayed.
630 * @param {array} classes -- list of additional CSS classes for button.
631 */
632 makeButton: function(buttonId, i18nPrefix, callback, pages, classes) {
633 var capitalizedId = buttonId.charAt(0).toUpperCase() + buttonId.slice(1);
634 this.buttonIds.push(buttonId);
635 var result = this.ownerDocument.createElement('button');
636 result.id = this.name() + '-' + buttonId + '-button';
637 result.classList.add('screen-control-button');
638 for (var i = 0; i < classes.length; i++) {
639 result.classList.add(classes[i]);
640 }
641 result.textContent = loadTimeData.
642 getString(i18nPrefix + capitalizedId + 'ButtonTitle');
643 result.addEventListener('click', function(e) {
644 callback(buttonId);
645 e.stopPropagation();
646 });
647 result.pages = pages;
648 return result;
649 },
650
651 /**
652 * Simple validator for |configureTextInput|.
653 * Element is considered valid if it has any text.
654 * @param {Element} element - element to be validated.
655 * @return {boolean} - true, if element has any text.
656 */
657 validIfNotEmpty_: function(element) {
658 return (element.value.length > 0);
659 },
660
661 /**
662 * Configure text-input |element|.
663 * @param {Element} element - element to be configured.
664 * @param {function(element)} inputChangeListener - function that will be
665 * called upon any button press/release.
666 * @param {function(element)} validator - function that will be called when
667 * Enter is pressed. If it returns |true| then advance to next element.
668 * @param {function(element)} moveFocus - function that will determine next
669 * element and move focus to it.
670 * @param {function(element)} errorHider - function that is called upon
671 * every button press, so that any associated error can be hidden.
672 */
673 configureTextInput: function(element,
674 inputChangeListener,
675 validator,
676 moveFocus,
677 errorHider) {
678 element.addEventListener('keydown', function(e) {
679 if (e.keyIdentifier == 'Enter') {
680 var dataValid = true;
681 if (validator)
682 dataValid = validator(element);
683 if (!dataValid) {
684 element.focus();
685 } else {
686 if (moveFocus)
687 moveFocus(element);
688 }
689 e.stopPropagation();
690 return;
691 }
692 if (errorHider)
693 errorHider(element);
694 if (inputChangeListener)
695 inputChangeListener(element);
696 });
697 element.addEventListener('keyup', function(e) {
698 if (inputChangeListener)
699 inputChangeListener(element);
700 });
701 },
702
703 /**
704 * Makes element from template.
705 * @param {string} templateId -- template will be looked up within screen
706 * by class with name "template-<templateId>".
707 * @param {string} elementId -- id for result, uinque within screen. Actual
708 * id will be prefixed with screen name. Use getScreenElement(id) to find
709 * it later.
710 */
711 makeFromTemplate: function(templateId, elementId) {
712 var templateClassName = 'template-' + templateId;
713 var templateNode = this.querySelector('.' + templateClassName);
714 var screenPrefix = this.name() + '-';
715 var result = templateNode.cloneNode(true);
716 result.classList.remove(templateClassName);
717 result.id = screenPrefix + elementId;
718 return result;
719 },
720
721 /**
722 * @param {string} buttonId -- id of button to be found,
723 * @return {Element} button created by makeButton with given buttonId.
724 */
725 getScreenButton: function(buttonId) {
726 var fullId = this.name() + '-' + buttonId + '-button';
727 return this.getScreenElement(buttonId + '-button');
728 },
729
730 /**
731 * @param {string} elementId -- id of element to be found,
732 * @return {Element} button created by makeFromTemplate with elementId.
733 */
734 getScreenElement: function(elementId) {
735 var fullId = this.name() + '-' + elementId;
736 return $(fullId);
737 },
738
739 /**
740 * Screen controls.
741 * @type {!Array} Array of Buttons.
742 */
743 get buttons() {
744 var links = this.ownerDocument.createElement('div');
745 var buttons = this.ownerDocument.createElement('div');
746 links.classList.add('controls-links');
747 buttons.classList.add('controls-buttons');
748
749 var importLink = this.makeFromTemplate('import-supervised-user-link',
750 'import-link');
751 importLink.hidden = true;
752 links.appendChild(importLink);
753
754 var linkElement = importLink.querySelector('.signin-link');
755 linkElement.addEventListener('click',
756 this.importLinkPressed_.bind(this));
757
758 var createLink = this.makeFromTemplate('create-supervised-user-link',
759 'create-link');
760 createLink.hidden = true;
761 links.appendChild(createLink);
762
763 var status = this.makeFromTemplate('status-container', 'status');
764 buttons.appendChild(status);
765
766 linkElement = createLink.querySelector('.signin-link');
767 linkElement.addEventListener('click',
768 this.createLinkPressed_.bind(this));
769
770 buttons.appendChild(this.makeButton(
771 'start',
772 'managedUserCreationFlow',
773 this.startButtonPressed_.bind(this),
774 ['intro'],
775 ['custom-appearance', 'button-fancy', 'button-blue']));
776
777 buttons.appendChild(this.makeButton(
778 'prev',
779 'managedUserCreationFlow',
780 this.prevButtonPressed_.bind(this),
781 ['manager'],
782 []));
783
784 buttons.appendChild(this.makeButton(
785 'next',
786 'managedUserCreationFlow',
787 this.nextButtonPressed_.bind(this),
788 ['manager', 'username'],
789 []));
790
791 buttons.appendChild(this.makeButton(
792 'import',
793 'managedUserCreationFlow',
794 this.importButtonPressed_.bind(this),
795 ['import', 'import-password'],
796 []));
797
798 buttons.appendChild(this.makeButton(
799 'gotit',
800 'managedUserCreationFlow',
801 this.gotItButtonPressed_.bind(this),
802 ['created'],
803 ['custom-appearance', 'button-fancy', 'button-blue']));
804 return [links, buttons];
805 },
806
807 /**
808 * Does sanity check and calls backend with current user name/password pair
809 * to authenticate manager. May result in showManagerPasswordError.
810 * @private
811 */
812 validateAndLogInAsManager_: function() {
813 var selectedPod = this.managerList_.selectedPod_;
814 if (null == selectedPod)
815 return;
816
817 var managerId = selectedPod.user.username;
818 var managerDisplayId = selectedPod.user.emailAddress;
819 var managerPassword = selectedPod.passwordElement.value;
820 if (managerPassword.length == 0)
821 return;
822 if (this.disabled)
823 return;
824 this.disabled = true;
825 this.context_.managerId = managerId;
826 this.context_.managerDisplayId = managerDisplayId;
827 this.context_.managerName = selectedPod.user.displayName;
828 chrome.send('authenticateManagerInLocallyManagedUserCreationFlow',
829 [managerId, managerPassword]);
830 },
831
832 /**
833 * Does sanity check and calls backend with user display name/password pair
834 * to create a user.
835 * @private
836 */
837 validateAndCreateLocallyManagedUser_: function() {
838 var firstPassword = $('managed-user-creation-password').value;
839 var secondPassword =
840 $('managed-user-creation-password-confirm').value;
841 var userName = $('managed-user-creation-name').value;
842 if (firstPassword != secondPassword) {
843 this.showPasswordError(
844 loadTimeData.getString('createManagedUserPasswordMismatchError'));
845 return;
846 }
847 if (this.disabled)
848 return;
849 this.disabled = true;
850
851 this.context_.managedName = userName;
852 chrome.send('specifyLocallyManagedUserCreationFlowUserData',
853 [userName, firstPassword]);
854 },
855
856 /**
857 * Does sanity check and calls backend with selected existing supervised
858 * user id to import user.
859 * @private
860 */
861 importSupervisedUser_: function() {
862 if (this.disabled)
863 return;
864 if (this.currentPage_ == 'import-password') {
865 var firstPassword = this.getScreenElement('password').value;
866 var secondPassword = this.getScreenElement('password-confirm').value;
867 if (firstPassword != secondPassword) {
868 this.showPasswordError(
869 loadTimeData.getString('createManagedUserPasswordMismatchError'));
870 return;
871 }
872 var userId = this.context_.importUserId;
873 this.disabled = true;
874 chrome.send('importSupervisedUserWithPassword',
875 [userId, firstPassword]);
876 return;
877 } else {
878 var selectedPod = this.importList_.selectedPod_;
879 if (!selectedPod)
880 return;
881 var user = selectedPod.user;
882 var userId = user.id;
883
884 this.context_.importUserId = userId;
885 this.context_.managedName = user.name;
886 this.context_.selectedImageUrl = user.avatarurl;
887 if (!user.needPassword) {
888 this.disabled = true;
889 chrome.send('importSupervisedUser', [userId]);
890 } else {
891 this.setVisiblePage_('import-password');
892 }
893 }
894 },
895
896 /**
897 * Calls backend part to check if current user name is valid/not taken.
898 * Results in call to either managedUserNameOk or managedUserNameError.
899 * @private
900 */
901 checkUserName_: function() {
902 var userName = this.getScreenElement('name').value;
903
904 // Avoid flickering
905 if (userName == this.lastIncorrectUserName_ ||
906 userName == this.lastVerifiedName_) {
907 return;
908 }
909 if (userName.length > 0) {
910 chrome.send('checkLocallyManagedUserName', [userName]);
911 } else {
912 this.nameErrorVisible = false;
913 this.lastVerifiedName_ = null;
914 this.lastIncorrectUserName_ = null;
915 this.updateNextButtonForUser_();
916 }
917 },
918
919 /**
920 * Called by backend part in case of successful name validation.
921 * @param {string} name - name that was validated.
922 */
923 managedUserNameOk: function(name) {
924 this.lastVerifiedName_ = name;
925 this.lastIncorrectUserName_ = null;
926 if ($('managed-user-creation-name').value == name)
927 this.clearUserNameError_();
928 this.updateNextButtonForUser_();
929 },
930
931 /**
932 * Called by backend part in case of name validation failure.
933 * @param {string} name - name that was validated.
934 * @param {string} errorText - reason why this name is invalid.
935 */
936 managedUserNameError: function(name, errorText) {
937 this.disabled = false;
938 this.lastIncorrectUserName_ = name;
939 this.lastVerifiedName_ = null;
940
941 var userNameField = $('managed-user-creation-name');
942 if (userNameField.value == this.lastIncorrectUserName_) {
943 this.nameErrorVisible = true;
944 $('bubble').showTextForElement(
945 $('managed-user-creation-name'),
946 errorText,
947 cr.ui.Bubble.Attachment.RIGHT,
948 12, 4);
949 this.setButtonDisabledStatus('next', true);
950 }
951 },
952
953 managedUserSuggestImport: function(name, user_id) {
954 this.disabled = false;
955 this.lastIncorrectUserName_ = name;
956 this.lastVerifiedName_ = null;
957
958 var userNameField = $('managed-user-creation-name');
959 var creationScreen = this;
960
961 if (userNameField.value == this.lastIncorrectUserName_) {
962 this.nameErrorVisible = true;
963 var link = this.ownerDocument.createElement('div');
964 link.innerHTML = loadTimeData.getStringF(
965 'importBubbleText',
966 '<a class="signin-link" href="#">',
967 name,
968 '</a>');
969 link.querySelector('.signin-link').addEventListener('click',
970 function(e) {
971 creationScreen.handleSuggestImport_(user_id);
972 e.stopPropagation();
973 });
974 $('bubble').showContentForElement(
975 $('managed-user-creation-name'),
976 cr.ui.Bubble.Attachment.RIGHT,
977 link,
978 12, 4);
979 this.setButtonDisabledStatus('next', true);
980 }
981 },
982
983 /**
984 * Clears user name error, if name is no more guaranteed to be invalid.
985 * @private
986 */
987 clearUserNameError_: function() {
988 // Avoid flickering
989 if ($('managed-user-creation-name').value ==
990 this.lastIncorrectUserName_) {
991 return;
992 }
993 this.nameErrorVisible = false;
994 },
995
996 /**
997 * Called by backend part in case of password validation failure.
998 * @param {string} errorText - reason why this password is invalid.
999 */
1000 showPasswordError: function(errorText) {
1001 $('bubble').showTextForElement(
1002 $('managed-user-creation-password'),
1003 errorText,
1004 cr.ui.Bubble.Attachment.RIGHT,
1005 12, 4);
1006 $('managed-user-creation-password').classList.add('password-error');
1007 $('managed-user-creation-password').focus();
1008 this.disabled = false;
1009 this.setButtonDisabledStatus('next', true);
1010 },
1011
1012 /**
1013 * True if user name error should be displayed.
1014 * @type {boolean}
1015 */
1016 set nameErrorVisible(value) {
1017 $('managed-user-creation-name').
1018 classList.toggle('duplicate-name', value);
1019 if (!value)
1020 $('bubble').hide();
1021 },
1022
1023 /**
1024 * Updates state of Continue button after minimal checks.
1025 * @return {boolean} true, if form seems to be valid.
1026 * @private
1027 */
1028 updateNextButtonForManager_: function() {
1029 var selectedPod = this.managerList_.selectedPod_;
1030 canProceed = null != selectedPod &&
1031 selectedPod.passwordElement.value.length > 0;
1032
1033 this.setButtonDisabledStatus('next', !canProceed);
1034 return canProceed;
1035 },
1036
1037 /**
1038 * Updates state of Continue button after minimal checks.
1039 * @return {boolean} true, if form seems to be valid.
1040 * @private
1041 */
1042 updateNextButtonForUser_: function() {
1043 var firstPassword = this.getScreenElement('password').value;
1044 var secondPassword = this.getScreenElement('password-confirm').value;
1045 var userName = this.getScreenElement('name').value;
1046
1047 var passwordOk = (firstPassword.length > 0) &&
1048 (firstPassword.length == secondPassword.length);
1049
1050 if (this.currentPage_ == 'import-password') {
1051 this.setButtonDisabledStatus('import', !passwordOk);
1052 return passwordOk;
1053 }
1054 var imageGrid = this.getScreenElement('image-grid');
1055 var imageChosen = !(imageGrid.selectionType == 'camera' &&
1056 imageGrid.cameraLive);
1057 var canProceed =
1058 passwordOk &&
1059 (userName.length > 0) &&
1060 this.lastVerifiedName_ &&
1061 (userName == this.lastVerifiedName_) &&
1062 imageChosen;
1063
1064 this.setButtonDisabledStatus('next', !canProceed);
1065 return canProceed;
1066 },
1067
1068 showSelectedManagerPasswordError_: function() {
1069 var selectedPod = this.managerList_.selectedPod_;
1070 selectedPod.showPasswordError();
1071 selectedPod.passwordElement.value = '';
1072 selectedPod.focusInput();
1073 this.updateNextButtonForManager_();
1074 },
1075
1076 /**
1077 * Enables one particular subpage and hides the rest.
1078 * @param {string} visiblePage - name of subpage.
1079 * @private
1080 */
1081 setVisiblePage_: function(visiblePage) {
1082 this.disabled = false;
1083 this.updateText_();
1084 $('bubble').hide();
1085 if (!this.imagesRequested_) {
1086 chrome.send('supervisedUserGetImages');
1087 this.imagesRequested_ = true;
1088 }
1089 var pageNames = ['intro',
1090 'manager',
1091 'username',
1092 'import',
1093 'error',
1094 'created'];
1095 var pageButtons = {'intro' : 'start',
1096 'error' : 'error',
1097 'import' : 'import',
1098 'import-password' : 'import',
1099 'created' : 'gotit'};
1100 this.hideStatus_();
1101 var pageToDisplay = visiblePage;
1102 if (visiblePage == 'import-password')
1103 pageToDisplay = 'username';
1104
1105 for (i in pageNames) {
1106 var pageName = pageNames[i];
1107 var page = $('managed-user-creation-' + pageName);
1108 page.hidden = (pageName != pageToDisplay);
1109 if (pageName == pageToDisplay)
1110 $('step-logo').hidden = page.classList.contains('step-no-logo');
1111 }
1112
1113 for (i in this.buttonIds) {
1114 var button = this.getScreenButton(this.buttonIds[i]);
1115 button.hidden = button.pages.indexOf(visiblePage) < 0;
1116 button.disabled = false;
1117 }
1118
1119 var pagesWithCancel = ['intro', 'manager', 'username', 'import-password',
1120 'error', 'import'];
1121 $('login-header-bar').allowCancel =
1122 pagesWithCancel.indexOf(visiblePage) > 0;
1123 $('cancel-add-user-button').disabled = false;
1124
1125 this.getScreenElement('import-link').hidden = true;
1126 this.getScreenElement('create-link').hidden = true;
1127
1128 if (pageButtons[visiblePage])
1129 this.getScreenButton(pageButtons[visiblePage]).focus();
1130
1131 this.currentPage_ = visiblePage;
1132
1133 if (visiblePage == 'manager' || visiblePage == 'intro') {
1134 $('managed-user-creation-password').classList.remove('password-error');
1135 if (this.managerList_.pods.length > 0)
1136 this.managerList_.selectPod(this.managerList_.pods[0]);
1137 }
1138
1139 if (visiblePage == 'username' || visiblePage == 'import-password') {
1140 var elements = this.getScreenElement(pageToDisplay).
1141 querySelectorAll('.hide-on-import');
1142 for (var i = 0; i < elements.length; i++) {
1143 elements[i].classList.toggle('hidden-on-import',
1144 visiblePage == 'import-password');
1145 }
1146 }
1147 if (visiblePage == 'username') {
1148 var imageGrid = this.getScreenElement('image-grid');
1149 // select some image.
1150 var selected = this.imagesData_[
1151 Math.floor(Math.random() * this.imagesData_.length)];
1152 this.context_.selectedImageUrl = selected.url;
1153 imageGrid.selectedItemUrl = selected.url;
1154 chrome.send('supervisedUserSelectImage',
1155 [selected.url, 'default']);
1156 this.getScreenElement('image-grid').redraw();
1157 this.checkUserName_();
1158 this.updateNextButtonForUser_();
1159 this.getScreenElement('name').focus();
1160 this.getScreenElement('import-link').hidden =
1161 this.importList_.pods.length == 0;
1162 } else if (visiblePage == 'import-password') {
1163 var imageGrid = this.getScreenElement('image-grid');
1164 var selected;
1165 if ('selectedImageUrl' in this.context_) {
1166 selected = this.context_.selectedImageUrl;
1167 } else {
1168 // select some image.
1169 selected = this.imagesData_[
1170 Math.floor(Math.random() * this.imagesData_.length)].url;
1171 chrome.send('supervisedUserSelectImage',
1172 [selected, 'default']);
1173 }
1174 imageGrid.selectedItemUrl = selected;
1175 this.getScreenElement('image-grid').redraw();
1176
1177 this.updateNextButtonForUser_();
1178
1179 this.getScreenElement('password').focus();
1180 this.getScreenElement('import-link').hidden = true;
1181 } else {
1182 this.getScreenElement('image-grid').stopCamera();
1183 }
1184 if (visiblePage == 'import') {
1185 this.getScreenElement('create-link').hidden = false;
1186 this.getScreenButton('import').disabled =
1187 !this.importList_.selectedPod_ ||
1188 this.importList_.selectedPod_.user.exists;
1189 }
1190 chrome.send('currentSupervisedUserPage', [this.currentPage_]);
1191 },
1192
1193 setButtonDisabledStatus: function(buttonName, status) {
1194 var button = $('managed-user-creation-' + buttonName + '-button');
1195 button.disabled = status;
1196 },
1197
1198 gotItButtonPressed_: function() {
1199 chrome.send('finishLocalManagedUserCreation');
1200 },
1201
1202 handleErrorButtonPressed_: function() {
1203 chrome.send('abortLocalManagedUserCreation');
1204 },
1205
1206 startButtonPressed_: function() {
1207 this.setVisiblePage_('manager');
1208 this.setButtonDisabledStatus('next', true);
1209 },
1210
1211 nextButtonPressed_: function() {
1212 if (this.currentPage_ == 'manager') {
1213 this.validateAndLogInAsManager_();
1214 return;
1215 }
1216 if (this.currentPage_ == 'username') {
1217 this.validateAndCreateLocallyManagedUser_();
1218 }
1219 },
1220
1221 importButtonPressed_: function() {
1222 this.importSupervisedUser_();
1223 },
1224
1225 importLinkPressed_: function() {
1226 this.setVisiblePage_('import');
1227 },
1228
1229 handleSuggestImport_: function(user_id) {
1230 this.setVisiblePage_('import');
1231 this.importList_.selectUser(user_id);
1232 },
1233
1234 createLinkPressed_: function() {
1235 this.setVisiblePage_('username');
1236 this.lastIncorrectUserName_ = null;
1237 this.lastVerifiedName_ = null;
1238 this.checkUserName_();
1239 },
1240
1241 prevButtonPressed_: function() {
1242 this.setVisiblePage_('intro');
1243 },
1244
1245 showProgress: function(text) {
1246 var status = this.getScreenElement('status');
1247 var statusText = status.querySelector('.id-text');
1248 statusText.textContent = text;
1249 statusText.classList.remove('error');
1250 status.querySelector('.id-spinner').hidden = false;
1251 status.hidden = false;
1252 this.getScreenElement('import-link').hidden = true;
1253 this.getScreenElement('create-link').hidden = true;
1254 },
1255
1256 showStatusError: function(text) {
1257 var status = this.getScreenElement('status');
1258 var statusText = status.querySelector('.id-text');
1259 statusText.textContent = text;
1260 statusText.classList.add('error');
1261 status.querySelector('.id-spinner').hidden = true;
1262 status.hidden = false;
1263 this.getScreenElement('import-link').hidden = true;
1264 this.getScreenElement('create-link').hidden = true;
1265 },
1266
1267 hideStatus_: function() {
1268 var status = this.getScreenElement('status');
1269 status.hidden = true;
1270 },
1271
1272 /**
1273 * Updates state of login header so that necessary buttons are displayed.
1274 **/
1275 onBeforeShow: function(data) {
1276 $('login-header-bar').signinUIState =
1277 SIGNIN_UI_STATE.MANAGED_USER_CREATION_FLOW;
1278 if (data['managers']) {
1279 this.loadManagers(data['managers']);
1280 }
1281 var imageGrid = this.getScreenElement('image-grid');
1282 imageGrid.updateAndFocus();
1283 },
1284
1285 /**
1286 * Update state of login header so that necessary buttons are displayed.
1287 */
1288 onBeforeHide: function() {
1289 $('login-header-bar').signinUIState = SIGNIN_UI_STATE.HIDDEN;
1290 this.getScreenElement('image-grid').stopCamera();
1291 },
1292
1293 /**
1294 * Returns a control which should receive an initial focus.
1295 */
1296 get defaultControl() {
1297 return $('managed-user-creation-name');
1298 },
1299
1300 /**
1301 * True if the the screen is disabled (handles no user interaction).
1302 * @type {boolean}
1303 */
1304 disabled_: false,
1305
1306 get disabled() {
1307 return this.disabled_;
1308 },
1309
1310 set disabled(value) {
1311 this.disabled_ = value;
1312 var controls = this.querySelectorAll('button,input');
1313 for (var i = 0, control; control = controls[i]; ++i) {
1314 control.disabled = value;
1315 }
1316 $('login-header-bar').disabled = value;
1317 $('cancel-add-user-button').disabled = false;
1318 },
1319
1320 /**
1321 * Called by backend part to propagate list of possible managers.
1322 * @param {Array} userList - list of users that can be managers.
1323 */
1324 loadManagers: function(userList) {
1325 $('managed-user-creation-managers-block').hidden = false;
1326 this.managerList_.clearPods();
1327 for (var i = 0; i < userList.length; ++i)
1328 this.managerList_.addPod(userList[i]);
1329 if (userList.length > 0)
1330 this.managerList_.selectPod(this.managerList_.pods[0]);
1331 },
1332
1333 /**
1334 * Cancels user creation and drops to user screen (either sign).
1335 */
1336 cancel: function() {
1337 var notSignedInPages = ['intro', 'manager'];
1338 var postCreationPages = ['created'];
1339 if (notSignedInPages.indexOf(this.currentPage_) >= 0) {
1340 // Make sure no manager password is kept:
1341 this.managerList_.clearPods();
1342
1343 $('pod-row').loadLastWallpaper();
1344
1345 Oobe.showScreen({id: SCREEN_ACCOUNT_PICKER});
1346 Oobe.resetSigninUI(true);
1347 return;
1348 }
1349 if (postCreationPages.indexOf(this.currentPage_) >= 0) {
1350 chrome.send('finishLocalManagedUserCreation');
1351 return;
1352 }
1353 chrome.send('abortLocalManagedUserCreation');
1354 },
1355
1356 updateText_: function() {
1357 var managerDisplayId = this.context_.managerDisplayId;
1358 this.updateElementText_('intro-alternate-text',
1359 'createManagedUserIntroAlternateText');
1360 this.updateElementText_('created-text-1',
1361 'createManagedUserCreatedText1',
1362 this.context_.managedName);
1363 // TODO(antrim): Move wrapping with strong in grd file, and eliminate this
1364 //call.
1365 this.updateElementText_('created-text-2',
1366 'createManagedUserCreatedText2',
1367 this.wrapStrong(
1368 loadTimeData.getString('managementURL')),
1369 this.context_.managedName);
1370 this.updateElementText_('created-text-3',
1371 'createManagedUserCreatedText3',
1372 managerDisplayId);
1373 this.updateElementText_('name-explanation',
1374 'createManagedUserNameExplanation',
1375 managerDisplayId);
1376 },
1377
1378 wrapStrong: function(original) {
1379 if (original == undefined)
1380 return original;
1381 return '<strong>' + original + '</strong>';
1382 },
1383
1384 updateElementText_: function(localId, templateName) {
1385 var args = Array.prototype.slice.call(arguments);
1386 args.shift();
1387 this.getScreenElement(localId).innerHTML =
1388 loadTimeData.getStringF.apply(loadTimeData, args);
1389 },
1390
1391 showIntroPage: function() {
1392 $('managed-user-creation-password').value = '';
1393 $('managed-user-creation-password-confirm').value = '';
1394 $('managed-user-creation-name').value = '';
1395
1396 this.lastVerifiedName_ = null;
1397 this.lastIncorrectUserName_ = null;
1398 this.passwordErrorVisible = false;
1399 $('managed-user-creation-password').classList.remove('password-error');
1400 this.nameErrorVisible = false;
1401
1402 this.setVisiblePage_('intro');
1403 },
1404
1405 showManagerPage: function() {
1406 this.setVisiblePage_('manager');
1407 },
1408
1409 showUsernamePage: function() {
1410 this.setVisiblePage_('username');
1411 },
1412
1413 showTutorialPage: function() {
1414 this.setVisiblePage_('created');
1415 },
1416
1417 showPage: function(page) {
1418 this.setVisiblePage_(page);
1419 },
1420
1421 showErrorPage: function(errorTitle, errorText, errorButtonText) {
1422 this.disabled = false;
1423 $('managed-user-creation-error-title').innerHTML = errorTitle;
1424 $('managed-user-creation-error-text').innerHTML = errorText;
1425 $('managed-user-creation-error-button').textContent = errorButtonText;
1426 this.setVisiblePage_('error');
1427 },
1428
1429 showManagerPasswordError: function() {
1430 this.disabled = false;
1431 this.showSelectedManagerPasswordError_();
1432 },
1433
1434 /*
1435 TODO(antrim) : this is an explicit code duplications with UserImageScreen.
1436 It should be removed by issue 251179.
1437 */
1438 /**
1439 * Currently selected user image index (take photo button is with zero
1440 * index).
1441 * @type {number}
1442 */
1443 selectedUserImage_: -1,
1444 imagesData: [],
1445
1446 setDefaultImages: function(imagesData) {
1447 var imageGrid = this.getScreenElement('image-grid');
1448 for (var i = 0, data; data = imagesData[i]; i++) {
1449 var item = imageGrid.addItem(data.url, data.title);
1450 item.type = 'default';
1451 item.author = data.author || '';
1452 item.website = data.website || '';
1453 }
1454 this.imagesData_ = imagesData;
1455 },
1456
1457
1458 handleActivate_: function() {
1459 var imageGrid = this.getScreenElement('image-grid');
1460 if (imageGrid.selectedItemUrl == ButtonImages.TAKE_PHOTO) {
1461 this.handleTakePhoto_();
1462 return;
1463 }
1464 this.nextButtonPressed_();
1465 },
1466
1467 /**
1468 * Handles selection change.
1469 * @param {Event} e Selection change event.
1470 * @private
1471 */
1472 handleSelect_: function(e) {
1473 var imageGrid = this.getScreenElement('image-grid');
1474 this.updateNextButtonForUser_();
1475
1476 $('managed-user-creation-flip-photo').tabIndex =
1477 (imageGrid.selectionType == 'camera') ? 0 : -1;
1478 if (imageGrid.cameraLive || imageGrid.selectionType != 'camera')
1479 imageGrid.previewElement.classList.remove('phototaken');
1480 else
1481 imageGrid.previewElement.classList.add('phototaken');
1482
1483 if (!imageGrid.cameraLive || imageGrid.selectionType != 'camera') {
1484 this.context_.selectedImageUrl = imageGrid.selectedItemUrl;
1485 chrome.send('supervisedUserSelectImage',
1486 [imageGrid.selectedItemUrl, imageGrid.selectionType]);
1487 }
1488 // Start/stop camera on (de)selection.
1489 if (!imageGrid.inProgramSelection &&
1490 imageGrid.selectionType != e.oldSelectionType) {
1491 if (imageGrid.selectionType == 'camera') {
1492 // Programmatic selection of camera item is done in
1493 // startCamera callback where streaming is started by itself.
1494 imageGrid.startCamera(
1495 function() {
1496 // Start capture if camera is still the selected item.
1497 $('managed-user-creation-image-preview-img').classList.toggle(
1498 'animated-transform', true);
1499 return imageGrid.selectedItem == imageGrid.cameraImage;
1500 });
1501 } else {
1502 $('managed-user-creation-image-preview-img').classList.toggle(
1503 'animated-transform', false);
1504 imageGrid.stopCamera();
1505 }
1506 }
1507 },
1508
1509 /**
1510 * Handle camera-photo flip.
1511 */
1512 handleFlipPhoto_: function() {
1513 var imageGrid = this.getScreenElement('image-grid');
1514 imageGrid.previewElement.classList.add('animation');
1515 imageGrid.flipPhoto = !imageGrid.flipPhoto;
1516 var flipMessageId = imageGrid.flipPhoto ?
1517 'photoFlippedAccessibleText' : 'photoFlippedBackAccessibleText';
1518 announceAccessibleMessage(loadTimeData.getString(flipMessageId));
1519 },
1520
1521 /**
1522 * Handle photo capture from the live camera stream.
1523 */
1524 handleTakePhoto_: function(e) {
1525 this.getScreenElement('image-grid').takePhoto();
1526 chrome.send('supervisedUserTakePhoto');
1527 },
1528
1529 handlePhotoTaken_: function(e) {
1530 chrome.send('supervisedUserPhotoTaken', [e.dataURL]);
1531 announceAccessibleMessage(
1532 loadTimeData.getString('photoCaptureAccessibleText'));
1533 },
1534
1535 /**
1536 * Handle photo updated event.
1537 * @param {Event} e Event with 'dataURL' property containing a data URL.
1538 */
1539 handlePhotoUpdated_: function(e) {
1540 chrome.send('supervisedUserPhotoTaken', [e.dataURL]);
1541 },
1542
1543 /**
1544 * Handle discarding the captured photo.
1545 */
1546 handleDiscardPhoto_: function(e) {
1547 var imageGrid = this.getScreenElement('image-grid');
1548 imageGrid.discardPhoto();
1549 chrome.send('supervisedUserDiscardPhoto');
1550 announceAccessibleMessage(
1551 loadTimeData.getString('photoDiscardAccessibleText'));
1552 },
1553
1554 setCameraPresent: function(present) {
1555 this.getScreenElement('image-grid').cameraPresent = present;
1556 },
1557
1558 setExistingManagedUsers: function(users) {
1559 var selectedUser = null;
1560 // Store selected user
1561 if (this.importList_.selectedPod)
1562 selectedUser = this.importList_.selectedPod.user.id;
1563
1564 var userList = users;
1565 userList.sort(function(a, b) {
1566 // Put existing users last.
1567 if (a.exists != b.exists)
1568 return a.exists ? 1 : -1;
1569 // Sort rest by name.
1570 return a.name.localeCompare(b.name, [], {sensitivity: 'base'});
1571 });
1572
1573 this.importList_.clearPods();
1574 var selectedIndex = -1;
1575 for (var i = 0; i < userList.length; ++i) {
1576 this.importList_.addPod(userList[i]);
1577 if (selectedUser == userList[i].id)
1578 selectedIndex = i;
1579 }
1580
1581 if (userList.length == 1)
1582 this.importList_.selectPod(this.importList_.pods[0]);
1583
1584 if (selectedIndex >= 0)
1585 this.importList_.selectPod(this.importList_.pods[selectedIndex]);
1586
1587 if (this.currentPage_ == 'username')
1588 this.getScreenElement('import-link').hidden = (userList.length == 0);
1589 },
1590 };
1591 });
1592
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698