OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * @fileoverview Oobe signin screen implementation. | 6 * @fileoverview Oobe signin screen implementation. |
7 */ | 7 */ |
8 | 8 |
9 cr.define('login', function() { | 9 cr.define('login', function() { |
10 | 10 |
(...skipping 12 matching lines...) Expand all Loading... |
23 GaiaSigninScreen.decorate(screen); | 23 GaiaSigninScreen.decorate(screen); |
24 Oobe.getInstance().registerScreen(screen); | 24 Oobe.getInstance().registerScreen(screen); |
25 window.addEventListener('message', | 25 window.addEventListener('message', |
26 screen.onMessage_.bind(screen), false); | 26 screen.onMessage_.bind(screen), false); |
27 }; | 27 }; |
28 | 28 |
29 GaiaSigninScreen.prototype = { | 29 GaiaSigninScreen.prototype = { |
30 __proto__: HTMLDivElement.prototype, | 30 __proto__: HTMLDivElement.prototype, |
31 | 31 |
32 // Authentication extension's start page URL. | 32 // Authentication extension's start page URL. |
33 extension_url_: null, | 33 extensionUrl_: null, |
| 34 |
| 35 // Whether extension should be loaded silently. |
| 36 silentLoad_: false, |
| 37 |
| 38 // Whether there is focused element. |
| 39 hasFocused_: false, |
34 | 40 |
35 // Number of times that we reload extension frame. | 41 // Number of times that we reload extension frame. |
36 retryCount_: 0, | 42 retryCount_: 0, |
37 | 43 |
38 // Timer id of pending retry. | 44 // Timer id of pending retry. |
39 retryTimer_: undefined, | 45 retryTimer_: undefined, |
40 | 46 |
41 /** @inheritDoc */ | 47 /** @inheritDoc */ |
42 decorate: function() { | 48 decorate: function() { |
| 49 this.frame_ = $('signin-frame'); |
| 50 |
43 $('createAccount').innerHTML = localStrings.getStringF( | 51 $('createAccount').innerHTML = localStrings.getStringF( |
44 'createAccount', | 52 'createAccount', |
45 '<a id="createAccountLink" class="signin-link" href="#">', | 53 '<a id="createAccountLink" class="signin-link" href="#">', |
46 '</a>'); | 54 '</a>'); |
47 $('guestSignin').innerHTML = localStrings.getStringF( | 55 $('guestSignin').innerHTML = localStrings.getStringF( |
48 'guestSignin', | 56 'guestSignin', |
49 '<a id="guestSigninLink" class="signin-link" href="#">', | 57 '<a id="guestSigninLink" class="signin-link" href="#">', |
50 '</a>'); | 58 '</a>'); |
51 $('createAccountLink').onclick = function() { | 59 $('createAccountLink').onclick = function() { |
52 chrome.send('createAccount'); | 60 chrome.send('createAccount'); |
53 }; | 61 }; |
54 $('guestSigninLink').onclick = function() { | 62 $('guestSigninLink').onclick = function() { |
55 chrome.send('launchIncognito'); | 63 chrome.send('launchIncognito'); |
56 }; | 64 }; |
| 65 document.addEventListener( |
| 66 'focusin', this.selfBind_(this.onFocusIn_.bind(this))); |
57 }, | 67 }, |
58 | 68 |
59 /** | 69 /** |
60 * Header text of the screen. | 70 * Header text of the screen. |
61 * @type {string} | 71 * @type {string} |
62 */ | 72 */ |
63 get header() { | 73 get header() { |
64 return localStrings.getString('signinScreenTitle'); | 74 return localStrings.getString('signinScreenTitle'); |
65 }, | 75 }, |
66 | 76 |
67 /** | 77 /** |
68 * Shows/hides loading UI. | 78 * Shows/hides loading UI. |
69 * @param {boolean} show True to show loading UI. | 79 * @param {boolean} show True to show loading UI. |
70 * @private | 80 * @private |
71 */ | 81 */ |
72 showLoadingUI_: function(show) { | 82 showLoadingUI_: function(show) { |
73 $('gaia-loading').hidden = !show; | 83 $('gaia-loading').hidden = !show; |
74 $('signin-frame').hidden = show; | 84 this.frame_.hidden = show; |
75 | 85 |
76 // Sign-in right panel is hidden if all its items are hidden. | 86 // Sign-in right panel is hidden if all its items are hidden. |
77 $('signin-right').hidden = show || | 87 $('signin-right').hidden = show || |
78 ($('createAccount').hidden && $('guestSignin').hidden); | 88 ($('createAccount').hidden && $('guestSignin').hidden); |
79 }, | 89 }, |
80 | 90 |
81 /** | 91 /** |
82 * Whether Gaia is loading. | 92 * Whether Gaia is loading. |
83 * @type {boolean} | 93 * @type {boolean} |
84 */ | 94 */ |
(...skipping 15 matching lines...) Expand all Loading... |
100 onBeforeShow: function(data) { | 110 onBeforeShow: function(data) { |
101 // Announce the name of the screen, if accessibility is on. | 111 // Announce the name of the screen, if accessibility is on. |
102 $('gaia-signin-aria-label').setAttribute( | 112 $('gaia-signin-aria-label').setAttribute( |
103 'aria-label', localStrings.getString('signinScreenTitle')); | 113 'aria-label', localStrings.getString('signinScreenTitle')); |
104 | 114 |
105 // Button header is always visible when sign in is presented. | 115 // Button header is always visible when sign in is presented. |
106 // Header is hidden once GAIA reports on successful sign in. | 116 // Header is hidden once GAIA reports on successful sign in. |
107 Oobe.getInstance().headerHidden = false; | 117 Oobe.getInstance().headerHidden = false; |
108 }, | 118 }, |
109 | 119 |
110 setExtensionUrl_: function(data) { | 120 /** |
| 121 * Returns function which gets an event and passes it and self to listener. |
| 122 * @param {!Object} listener Listener to be wrapped. |
| 123 */ |
| 124 selfBind_: function(listener) { |
| 125 var selfBinded = function(e) { |
| 126 listener(e, selfBinded); |
| 127 } |
| 128 return selfBinded; |
| 129 }, |
| 130 |
| 131 /** |
| 132 * Tracks first focus in event. |
| 133 * @param {!Object} e Focus in event. |
| 134 * @param {!Object} listener Listener which shold be removed from event |
| 135 * listeners list. |
| 136 */ |
| 137 onFocusIn_: function(e, listener) { |
| 138 this.hasFocused_ = true; |
| 139 document.removeEventListener('focusin', listener); |
| 140 }, |
| 141 |
| 142 /** |
| 143 * Restore focus back to the focused element. |
| 144 * @param {!Object} e Focus out event. |
| 145 * @param {!Object} listener Listener which shold be removed from event |
| 146 * listeners list. |
| 147 */ |
| 148 onFocusOut_: function(e, listener) { |
| 149 window.setTimeout(e.target.focus.bind(e.target), 0); |
| 150 document.removeEventListener('focusout', listener); |
| 151 }, |
| 152 |
| 153 loadAuthExtension_: function(data) { |
| 154 this.silentLoad_ = data.silentLoad; |
| 155 |
111 $('createAccount').hidden = !data.createAccount; | 156 $('createAccount').hidden = !data.createAccount; |
112 $('guestSignin').hidden = !data.guestSignin; | 157 $('guestSignin').hidden = !data.guestSignin; |
113 | 158 |
114 var params = []; | 159 var params = []; |
115 if (data.gaiaOrigin) | 160 if (data.gaiaOrigin) |
116 params.push('gaiaOrigin=' + encodeURIComponent(data.gaiaOrigin)); | 161 params.push('gaiaOrigin=' + encodeURIComponent(data.gaiaOrigin)); |
117 if (data.hl) | 162 if (data.hl) |
118 params.push('hl=' + encodeURIComponent(data.hl)); | 163 params.push('hl=' + encodeURIComponent(data.hl)); |
119 if (data.email) | 164 if (data.email) |
120 params.push('email=' + encodeURIComponent(data.email)); | 165 params.push('email=' + encodeURIComponent(data.email)); |
121 if (data.test_email) | 166 if (data.test_email) |
122 params.push('test_email=' + encodeURIComponent(data.test_email)); | 167 params.push('test_email=' + encodeURIComponent(data.test_email)); |
123 if (data.test_password) | 168 if (data.test_password) |
124 params.push('test_password=' + encodeURIComponent(data.test_password)); | 169 params.push('test_password=' + encodeURIComponent(data.test_password)); |
125 | 170 |
126 var url = data.startUrl; | 171 var url = data.startUrl; |
127 if (params.length) | 172 if (params.length) |
128 url += '?' + params.join('&'); | 173 url += '?' + params.join('&'); |
129 | 174 |
130 if (data.forceReload || this.extension_url_ != url) { | 175 if (data.forceReload || this.extensionUrl_ != url) { |
131 console.log('Opening extension: ' + data.startUrl + | 176 console.log('Opening extension: ' + data.startUrl + |
132 ', opt_email=' + data.email); | 177 ', opt_email=' + data.email); |
133 | 178 |
134 $('signin-frame').src = url; | 179 this.frame_.src = url; |
135 this.extension_url_ = url; | 180 this.extensionUrl_ = url; |
136 | 181 |
137 this.loading = true; | 182 this.loading = true; |
138 this.clearRetry_(); | 183 this.clearRetry_(); |
139 } else if (this.loading) { | 184 } else if (this.loading) { |
140 // Probably an error has occurred, so trying to reload. | 185 // Probably an error has occurred, so trying to reload. |
141 this.doReload(); | 186 this.doReload(); |
142 } | 187 } |
143 }, | 188 }, |
144 | 189 |
145 /** | 190 /** |
146 * Checks if message comes from the loaded authentication extension. | 191 * Checks if message comes from the loaded authentication extension. |
147 * @param e {object} Payload of the received HTML5 message. | 192 * @param e {object} Payload of the received HTML5 message. |
148 * @type {bool} | 193 * @type {bool} |
149 */ | 194 */ |
150 isAuthExtMessage_: function(e) { | 195 isAuthExtMessage_: function(e) { |
151 return this.extension_url_ != null && | 196 return this.extensionUrl_ != null && |
152 this.extension_url_.indexOf(e.origin) == 0 && | 197 this.extensionUrl_.indexOf(e.origin) == 0 && |
153 e.source == $('signin-frame').contentWindow; | 198 e.source == this.frame_.contentWindow; |
154 }, | 199 }, |
155 | 200 |
156 /** | 201 /** |
157 * Event handler that is invoked when HTML5 message is received. | 202 * Event handler that is invoked when HTML5 message is received. |
158 * @param e {object} Payload of the received HTML5 message. | 203 * @param e {object} Payload of the received HTML5 message. |
159 */ | 204 */ |
160 onMessage_: function(e) { | 205 onMessage_: function(e) { |
161 var msg = e.data; | 206 var msg = e.data; |
162 if (msg.method == 'completeLogin' && this.isAuthExtMessage_(e)) { | 207 if (msg.method == 'completeLogin' && this.isAuthExtMessage_(e)) { |
163 chrome.send('completeLogin', [msg.email, msg.password] ); | 208 chrome.send('completeLogin', [msg.email, msg.password] ); |
164 this.loading = true; | 209 this.loading = true; |
165 // Now that we're in logged in state header should be hidden. | 210 // Now that we're in logged in state header should be hidden. |
166 Oobe.getInstance().headerHidden = true; | 211 Oobe.getInstance().headerHidden = true; |
167 } else if (msg.method == 'loginUILoaded' && this.isAuthExtMessage_(e)) { | 212 } else if (msg.method == 'loginUILoaded' && this.isAuthExtMessage_(e)) { |
| 213 // TODO(altimofeev): there is no guarantee that next 'focusout' event |
| 214 // will be caused by the extension, so better approach is direct asking |
| 215 // the extension (and gaia consequently) to not grab the focus. |
| 216 if (this.silentLoad_ && this.hasFocused_) { |
| 217 document.addEventListener( |
| 218 'focusout', this.selfBind_(this.onFocusOut_.bind(this))); |
| 219 } |
168 $('error-message').update(); | 220 $('error-message').update(); |
169 this.loading = false; | 221 this.loading = false; |
170 this.clearRetry_(); | 222 this.clearRetry_(); |
171 chrome.send('loginWebuiReady'); | 223 chrome.send('loginWebuiReady'); |
172 } | 224 } |
173 }, | 225 }, |
174 | 226 |
175 /** | 227 /** |
176 * Clears input fields and switches to input mode. | 228 * Clears input fields and switches to input mode. |
177 * @param {boolean} takeFocus True to take focus. | 229 * @param {boolean} takeFocus True to take focus. |
(...skipping 14 matching lines...) Expand all Loading... |
192 window.clearTimeout(this.retryTimer_); | 244 window.clearTimeout(this.retryTimer_); |
193 this.retryTimer_ = undefined; | 245 this.retryTimer_ = undefined; |
194 } | 246 } |
195 }, | 247 }, |
196 | 248 |
197 /** | 249 /** |
198 * Reloads extension frame. | 250 * Reloads extension frame. |
199 */ | 251 */ |
200 doReload: function() { | 252 doReload: function() { |
201 console.log('Reload auth extension frame.'); | 253 console.log('Reload auth extension frame.'); |
202 $('signin-frame').src = this.extension_url_; | 254 this.frame_.src = this.extensionUrl_; |
203 this.retryTimer_ = undefined; | 255 this.retryTimer_ = undefined; |
204 }, | 256 }, |
205 | 257 |
206 /** | 258 /** |
207 * Schedules extension frame reload. | 259 * Schedules extension frame reload. |
208 */ | 260 */ |
209 scheduleRetry: function() { | 261 scheduleRetry: function() { |
210 if (this.retryCount_ >= 3 || this.retryTimer_) | 262 if (this.retryCount_ >= 3 || this.retryTimer_) |
211 return; | 263 return; |
212 | 264 |
213 const MAX_DELAY = 7200; // 7200 seconds (i.e. 2 hours) | 265 const MAX_DELAY = 7200; // 7200 seconds (i.e. 2 hours) |
214 const MIN_DELAY = 1; // 1 second | 266 const MIN_DELAY = 1; // 1 second |
215 | 267 |
216 var delay = Math.pow(2, this.retryCount_) * 5; | 268 var delay = Math.pow(2, this.retryCount_) * 5; |
217 delay = Math.max(MIN_DELAY, Math.min(MAX_DELAY, delay)) * 1000; | 269 delay = Math.max(MIN_DELAY, Math.min(MAX_DELAY, delay)) * 1000; |
218 | 270 |
219 ++this.retryCount_; | 271 ++this.retryCount_; |
220 this.retryTimer_ = window.setTimeout(this.doReload.bind(this), delay); | 272 this.retryTimer_ = window.setTimeout(this.doReload.bind(this), delay); |
221 console.log('GaiaSigninScreen scheduleRetry in ' + delay + 'ms.'); | 273 console.log('GaiaSigninScreen scheduleRetry in ' + delay + 'ms.'); |
222 } | 274 } |
223 }; | 275 }; |
224 | 276 |
225 GaiaSigninScreen.setExtensionUrl = function(data) { | 277 GaiaSigninScreen.loadAuthExtension = function(data) { |
226 $('gaia-signin').setExtensionUrl_(data); | 278 $('gaia-signin').loadAuthExtension_(data); |
227 }; | 279 }; |
228 | 280 |
229 return { | 281 return { |
230 GaiaSigninScreen: GaiaSigninScreen | 282 GaiaSigninScreen: GaiaSigninScreen |
231 }; | 283 }; |
232 }); | 284 }); |
OLD | NEW |