cros: Remove default pinned apps trial.
[chromium-blink-merge.git] / chrome / browser / resources / chromeos / login / screen_gaia_signin.js
blobf0099e792b77f1a55fdf286b7ce4837baecede3c
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6  * @fileoverview Oobe signin screen implementation.
7  */
9 <include src="../../gaia_auth_host/gaia_auth_host.js"></include>
11 login.createScreen('GaiaSigninScreen', 'gaia-signin', function() {
12   // Gaia loading time after which error message must be displayed and
13   // lazy portal check should be fired.
14   /** @const */ var GAIA_LOADING_PORTAL_SUSSPECT_TIME_SEC = 7;
16   // Maximum Gaia loading time in seconds.
17   /** @const */ var MAX_GAIA_LOADING_TIME_SEC = 60;
19   /** @const */ var HELP_TOPIC_ENTERPRISE_REPORTING = 2535613;
21   return {
22     EXTERNAL_API: [
23       'loadAuthExtension',
24       'updateAuthExtension',
25       'doReload',
26       'onFrameError'
27     ],
29     /**
30      * Frame loading error code (0 - no error).
31      * @type {number}
32      * @private
33      */
34     error_: 0,
36     /**
37      * Saved gaia auth host load params.
38      * @type {?string}
39      * @private
40      */
41     gaiaAuthParams_: null,
43     /**
44      * Whether local version of Gaia page is used.
45      * @type {boolean}
46      * @private
47      */
48     isLocal_: false,
50     /**
51      * Email of the user, which is logging in using offline mode.
52      * @type {string}
53      */
54     email: '',
56     /**
57      * Timer id of pending load.
58      * @type {number}
59      * @private
60      */
61     loadingTimer_: undefined,
63     /**
64      * Whether user can cancel Gaia screen.
65      * @type {boolean}
66      * @private
67      */
68     cancelAllowed_: undefined,
70     /** @override */
71     decorate: function() {
72       this.gaiaAuthHost_ = new cr.login.GaiaAuthHost($('signin-frame'));
73       this.gaiaAuthHost_.addEventListener(
74           'ready', this.onAuthReady_.bind(this));
75       this.gaiaAuthHost_.confirmPasswordCallback =
76           this.onAuthConfirmPassword_.bind(this);
77       this.gaiaAuthHost_.noPasswordCallback =
78           this.onAuthNoPassword_.bind(this);
79       this.gaiaAuthHost_.authPageLoadedCallback =
80           this.onAuthPageLoaded_.bind(this);
82       $('enterprise-info-hint-link').addEventListener('click', function(e) {
83         chrome.send('launchHelpApp', [HELP_TOPIC_ENTERPRISE_REPORTING]);
84         e.preventDefault();
85       });
88       this.updateLocalizedContent();
89     },
91     /**
92      * Header text of the screen.
93      * @type {string}
94      */
95     get header() {
96       return loadTimeData.getString('signinScreenTitle');
97     },
99     /**
100      * Returns true if local version of Gaia is used.
101      * @type {boolean}
102      */
103     get isLocal() {
104       return this.isLocal_;
105     },
107     /**
108      * Sets whether local version of Gaia is used.
109      * @param {boolean} value Whether local version of Gaia is used.
110      */
111     set isLocal(value) {
112       this.isLocal_ = value;
113       chrome.send('updateOfflineLogin', [value]);
114     },
116     /**
117      * Shows/hides loading UI.
118      * @param {boolean} show True to show loading UI.
119      * @private
120      */
121     showLoadingUI_: function(show) {
122       $('gaia-loading').hidden = !show;
123       this.gaiaAuthHost_.frame.hidden = show;
124       $('signin-right').hidden = show;
125       $('enterprise-info-container').hidden = show;
126       $('gaia-signin-divider').hidden = show;
127     },
129     /**
130      * Handler for Gaia loading suspiciously long timeout.
131      * @private
132      */
133     onLoadingSuspiciouslyLong_: function() {
134       if (this != Oobe.getInstance().currentScreen)
135         return;
136       chrome.send('showLoadingTimeoutError');
137       this.loadingTimer_ = window.setTimeout(
138           this.onLoadingTimeOut_.bind(this),
139           (MAX_GAIA_LOADING_TIME_SEC - GAIA_LOADING_PORTAL_SUSSPECT_TIME_SEC) *
140           1000);
141     },
143     /**
144      * Handler for Gaia loading timeout.
145      * @private
146      */
147     onLoadingTimeOut_: function() {
148       this.loadingTimer_ = undefined;
149       chrome.send('showLoadingTimeoutError');
150     },
152     /**
153      * Clears loading timer.
154      * @private
155      */
156     clearLoadingTimer_: function() {
157       if (this.loadingTimer_) {
158         window.clearTimeout(this.loadingTimer_);
159         this.loadingTimer_ = undefined;
160       }
161     },
163     /**
164      * Sets up loading timer.
165      * @private
166      */
167     startLoadingTimer_: function() {
168       this.clearLoadingTimer_();
169       this.loadingTimer_ = window.setTimeout(
170           this.onLoadingSuspiciouslyLong_.bind(this),
171           GAIA_LOADING_PORTAL_SUSSPECT_TIME_SEC * 1000);
172     },
174     /**
175      * Whether Gaia is loading.
176      * @type {boolean}
177      */
178     get loading() {
179       return !$('gaia-loading').hidden;
180     },
181     set loading(loading) {
182       if (loading == this.loading)
183         return;
185       this.showLoadingUI_(loading);
186     },
188     /**
189      * Event handler that is invoked just before the frame is shown.
190      * @param {string} data Screen init payload. Url of auth extension start
191      *                      page.
192      */
193     onBeforeShow: function(data) {
194       chrome.send('loginUIStateChanged', ['gaia-signin', true]);
195       $('login-header-bar').signinUIState = SIGNIN_UI_STATE.GAIA_SIGNIN;
197       // Ensure that GAIA signin (or loading UI) is actually visible.
198       window.webkitRequestAnimationFrame(function() {
199         chrome.send('loginVisible', ['gaia-loading']);
200       });
202       // Announce the name of the screen, if accessibility is on.
203       $('gaia-signin-aria-label').setAttribute(
204           'aria-label', loadTimeData.getString('signinScreenTitle'));
206       // Button header is always visible when sign in is presented.
207       // Header is hidden once GAIA reports on successful sign in.
208       Oobe.getInstance().headerHidden = false;
209     },
211     /**
212      * Event handler that is invoked just before the screen is hidden.
213      */
214     onBeforeHide: function() {
215       chrome.send('loginUIStateChanged', ['gaia-signin', false]);
216       $('login-header-bar').signinUIState = SIGNIN_UI_STATE.HIDDEN;
217     },
219     /**
220      * Loads the authentication extension into the iframe.
221      * @param {Object} data Extension parameters bag.
222      * @private
223      */
224     loadAuthExtension: function(data) {
225       this.isLocal = data.isLocal;
226       this.email = '';
227       this.classList.toggle('saml', false);
229       this.updateAuthExtension(data);
231       var params = {};
232       for (var i in cr.login.GaiaAuthHost.SUPPORTED_PARAMS) {
233         var name = cr.login.GaiaAuthHost.SUPPORTED_PARAMS[i];
234         if (data[name])
235           params[name] = data[name];
236       }
238       if (data.localizedStrings)
239         params.localizedStrings = data.localizedStrings;
241       if (data.forceReload ||
242           JSON.stringify(this.gaiaAuthParams_) != JSON.stringify(params)) {
243         this.error_ = 0;
244         this.gaiaAuthHost_.load(data.useOffline ?
245                                     cr.login.GaiaAuthHost.AuthMode.OFFLINE :
246                                     cr.login.GaiaAuthHost.AuthMode.DEFAULT,
247                                 params,
248                                 this.onAuthCompleted_.bind(this));
249         this.gaiaAuthParams_ = params;
251         this.loading = true;
252         this.startLoadingTimer_();
253       } else if (this.loading && this.error_) {
254         // An error has occurred, so trying to reload.
255         this.doReload();
256       }
257     },
259     /**
260      * Updates the authentication extension with new parameters, if needed.
261      * @param {Object} data New extension parameters bag.
262      * @private
263      */
264     updateAuthExtension: function(data) {
265       var reasonLabel = $('gaia-signin-reason');
266       if (data.passwordChanged) {
267         reasonLabel.textContent =
268             loadTimeData.getString('signinScreenPasswordChanged');
269         reasonLabel.hidden = false;
270       } else {
271         reasonLabel.hidden = true;
272       }
274       $('createAccount').hidden = !data.createAccount;
275       $('guestSignin').hidden = !data.guestSignin;
276       $('createManagedUserPane').hidden = !data.managedUsersEnabled;
278       $('createManagedUserLinkPlaceholder').hidden =
279           !data.managedUsersCanCreate;
280       $('createManagedUserNoManagerText').hidden = data.managedUsersCanCreate;
281       $('createManagedUserNoManagerText').textContent =
282           data.managedUsersRestrictionReason;
284       // Allow cancellation of screen only when user pods can be displayed.
285       this.cancelAllowed_ = data.isShowUsers && $('pod-row').pods.length;
286       $('login-header-bar').allowCancel = this.cancelAllowed_;
288       // Sign-in right panel is hidden if all of its items are hidden.
289       var noRightPanel = $('gaia-signin-reason').hidden &&
290                          $('createAccount').hidden &&
291                          $('guestSignin').hidden &&
292                          $('createManagedUserPane').hidden;
293       this.classList.toggle('no-right-panel', noRightPanel);
294       if (Oobe.getInstance().currentScreen === this)
295         Oobe.getInstance().updateScreenSize(this);
296     },
298     /**
299      * Invoked when the auth host notifies about an auth page is loaded.
300      * @param {boolean} isSAML True if the loaded auth page is SAML.
301      */
302     onAuthPageLoaded_: function(isSAML) {
303       this.classList.toggle('saml', isSAML);
304       if (Oobe.getInstance().currentScreen === this)
305         Oobe.getInstance().updateScreenSize(this);
306     },
308     /**
309      * Invoked when the auth host emits 'ready' event.
310      * @private
311      */
312     onAuthReady_: function() {
313       this.loading = false;
314       this.clearLoadingTimer_();
316       // Show deferred error bubble.
317       if (this.errorBubble_) {
318         this.showErrorBubble(this.errorBubble_[0], this.errorBubble_[1]);
319         this.errorBubble_ = undefined;
320       }
322       chrome.send('loginWebuiReady');
323       chrome.send('loginVisible', ['gaia-signin']);
325       // Warm up the user images screen.
326       Oobe.getInstance().preloadScreen({id: SCREEN_USER_IMAGE_PICKER});
327     },
329     /**
330      * Invoked when the auth host needs the user to confirm password.
331      * @private
332      */
333     onAuthConfirmPassword_: function() {
334       this.loading = true;
335       Oobe.getInstance().headerHidden = false;
337       login.ConfirmPasswordScreen.show(
338           this.onConfirmPasswordCollected_.bind(this));
339     },
341     /**
342      * Invoked when the confirm password screen is dismissed.
343      * @private
344      */
345     onConfirmPasswordCollected_: function(password) {
346       this.gaiaAuthHost_.verifyConfirmedPassword(password);
348       // Shows signin UI again without changing states.
349       Oobe.showScreen({id: SCREEN_GAIA_SIGNIN});
350     },
352     /**
353      * Inovked when the auth flow completes but no password is available.
354      * @param {string} email The authenticated user email.
355      */
356     onAuthNoPassword_: function(email) {
357       login.MessageBoxScreen.show(
358           loadTimeData.getString('noPasswordWarningTitle'),
359           loadTimeData.getString('noPasswordWarningBody'),
360           loadTimeData.getString('noPasswordWarningOkButton'),
361           Oobe.showSigninUI);
362     },
364     /**
365      * Invoked when auth is completed successfully.
366      * @param {!Object} credentials Credentials of the completed authentication.
367      * @private
368      */
369     onAuthCompleted_: function(credentials) {
370       if (credentials.useOffline) {
371         this.email = credentials.email;
372         chrome.send('authenticateUser',
373                     [credentials.email, credentials.password]);
374       } else if (credentials.authCode) {
375         chrome.send('completeAuthentication',
376                     [credentials.email,
377                      credentials.password,
378                      credentials.authCode]);
379       } else {
380         chrome.send('completeLogin',
381                     [credentials.email, credentials.password]);
382       }
384       this.loading = true;
385       // Now that we're in logged in state header should be hidden.
386       Oobe.getInstance().headerHidden = true;
387       // Clear any error messages that were shown before login.
388       Oobe.clearErrors();
389     },
391     /**
392      * Clears input fields and switches to input mode.
393      * @param {boolean} takeFocus True to take focus.
394      * @param {boolean} forceOnline Whether online sign-in should be forced.
395      * If |forceOnline| is false previously used sign-in type will be used.
396      */
397     reset: function(takeFocus, forceOnline) {
398       // Reload and show the sign-in UI if needed.
399       if (takeFocus) {
400         if (!forceOnline && this.isLocal) {
401           // Show 'Cancel' button to allow user to return to the main screen
402           // (e.g. this makes sense when connection is back).
403           Oobe.getInstance().headerHidden = false;
404           $('login-header-bar').signinUIState = SIGNIN_UI_STATE.GAIA_SIGNIN;
405           // Do nothing, since offline version is reloaded after an error comes.
406         } else {
407           Oobe.showSigninUI();
408         }
409       }
410     },
412     /**
413      * Reloads extension frame.
414      */
415     doReload: function() {
416       this.error_ = 0;
417       this.gaiaAuthHost_.reload();
418       this.loading = true;
419       this.startLoadingTimer_();
420     },
422     /**
423      * Updates localized content of the screen that is not updated via template.
424      */
425     updateLocalizedContent: function() {
426       $('createAccount').innerHTML = loadTimeData.getStringF(
427           'createAccount',
428           '<a id="createAccountLink" class="signin-link" href="#">',
429           '</a>');
430       $('guestSignin').innerHTML = loadTimeData.getStringF(
431           'guestSignin',
432           '<a id="guestSigninLink" class="signin-link" href="#">',
433           '</a>');
434       $('createManagedUserLinkPlaceholder').innerHTML = loadTimeData.getStringF(
435             'createLocallyManagedUser',
436             '<a id="createManagedUserLink" class="signin-link" href="#">',
437             '</a>');
438       $('createAccountLink').addEventListener('click', function(e) {
439         chrome.send('createAccount');
440         e.preventDefault();
441       });
442       $('guestSigninLink').addEventListener('click', function(e) {
443         chrome.send('launchIncognito');
444         e.preventDefault();
445       });
446       $('createManagedUserLink').addEventListener('click', function(e) {
447         chrome.send('showLocallyManagedUserCreationScreen');
448         e.preventDefault();
449       });
450     },
452     /**
453      * Shows sign-in error bubble.
454      * @param {number} loginAttempts Number of login attemps tried.
455      * @param {HTMLElement} content Content to show in bubble.
456      */
457     showErrorBubble: function(loginAttempts, error) {
458       if (this.isLocal) {
459         $('add-user-button').hidden = true;
460         $('cancel-add-user-button').hidden = false;
461         // Reload offline version of the sign-in extension, which will show
462         // error itself.
463         chrome.send('offlineLogin', [this.email]);
464       } else if (!this.loading) {
465         // We want to show bubble near "Email" field, but we can't calculate
466         // it's position because it is located inside iframe. So we only
467         // can hardcode some constants.
468         /** @const */ var ERROR_BUBBLE_OFFSET = 84;
469         /** @const */ var ERROR_BUBBLE_PADDING = 0;
470         $('bubble').showContentForElement($('login-box'),
471                                           cr.ui.Bubble.Attachment.LEFT,
472                                           error,
473                                           ERROR_BUBBLE_OFFSET,
474                                           ERROR_BUBBLE_PADDING);
475       } else {
476         // Defer the bubble until the frame has been loaded.
477         this.errorBubble_ = [loginAttempts, error];
478       }
479     },
481     /**
482      * Called when user canceled signin.
483      */
484     cancel: function() {
485       if (!this.cancelAllowed_)
486         return;
487       $('pod-row').loadLastWallpaper();
488       Oobe.showScreen({id: SCREEN_ACCOUNT_PICKER});
489       Oobe.resetSigninUI(true);
490     },
492     /**
493      * Handler for iframe's error notification coming from the outside.
494      * For more info see C++ class 'SnifferObserver' which calls this method.
495      * @param {number} error Error code.
496      */
497     onFrameError: function(error) {
498       this.error_ = error;
499       chrome.send('frameLoadingCompleted', [this.error_]);
500     },
501   };