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

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

Issue 8564008: [cros,login] Restore the focus after hidden auth extension has grabbed it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: code review Created 9 years, 1 month 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
« no previous file with comments | « no previous file | chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 });
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698