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

Side by Side Diff: chrome/browser/resources/gaia_auth/main.js

Issue 171533014: Revert of Implement inline signin with iframe (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 10 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 * Authenticator class wraps the communications between Gaia and its host. 6 * Authenticator class wraps the communications between Gaia and its host.
7 */ 7 */
8 function Authenticator() { 8 function Authenticator() {
9 } 9 }
10 10
(...skipping 18 matching lines...) Expand all
29 Authenticator.prototype = { 29 Authenticator.prototype = {
30 email_: null, 30 email_: null,
31 password_: null, 31 password_: null,
32 attemptToken_: null, 32 attemptToken_: null,
33 33
34 // Input params from extension initialization URL. 34 // Input params from extension initialization URL.
35 inputLang_: undefined, 35 inputLang_: undefined,
36 intputEmail_: undefined, 36 intputEmail_: undefined,
37 37
38 isSAMLFlow_: false, 38 isSAMLFlow_: false,
39 isSAMLEnabled_: false, 39 samlSupportChannel_: null,
40 supportChannel_: null,
41 40
42 GAIA_URL: 'https://accounts.google.com/', 41 GAIA_URL: 'https://accounts.google.com/',
43 GAIA_PAGE_PATH: 'ServiceLogin?skipvpage=true&sarp=1&rm=hide', 42 GAIA_PAGE_PATH: 'ServiceLogin?skipvpage=true&sarp=1&rm=hide',
44 PARENT_PAGE: 'chrome://oobe/', 43 PARENT_PAGE: 'chrome://oobe/',
45 SERVICE_ID: 'chromeoslogin', 44 SERVICE_ID: 'chromeoslogin',
46 CONTINUE_URL: Authenticator.THIS_EXTENSION_ORIGIN + '/success.html', 45 CONTINUE_URL: Authenticator.THIS_EXTENSION_ORIGIN + '/success.html',
47 CONSTRAINED_FLOW_SOURCE: 'chrome', 46 CONSTRAINED_FLOW_SOURCE: 'chrome',
48 47
49 initialize: function() { 48 initialize: function() {
50 var params = getUrlSearchParams(location.search); 49 var params = getUrlSearchParams(location.search);
51 this.parentPage_ = params.parentPage || this.PARENT_PAGE; 50 this.parentPage_ = params.parentPage || this.PARENT_PAGE;
52 this.gaiaUrl_ = params.gaiaUrl || this.GAIA_URL; 51 this.gaiaUrl_ = params.gaiaUrl || this.GAIA_URL;
53 this.gaiaPath_ = params.gaiaPath || this.GAIA_PAGE_PATH; 52 this.gaiaPath_ = params.gaiaPath || this.GAIA_PAGE_PATH;
54 this.inputLang_ = params.hl; 53 this.inputLang_ = params.hl;
55 this.inputEmail_ = params.email; 54 this.inputEmail_ = params.email;
56 this.service_ = params.service || this.SERVICE_ID; 55 this.service_ = params.service || this.SERVICE_ID;
57 this.continueUrl_ = params.continueUrl || this.CONTINUE_URL; 56 this.continueUrl_ = params.continueUrl || this.CONTINUE_URL;
58 this.desktopMode_ = params.desktopMode == '1'; 57 this.continueUrlWithoutParams_ = stripParams(this.continueUrl_);
59 this.isConstrainedWindow_ = params.constrained == '1'; 58 this.inlineMode_ = params.inlineMode == '1';
59 this.constrained_ = params.constrained == '1';
60 this.partitionId_ = params.partitionId || '';
60 this.initialFrameUrl_ = params.frameUrl || this.constructInitialFrameUrl_(); 61 this.initialFrameUrl_ = params.frameUrl || this.constructInitialFrameUrl_();
61 this.initialFrameUrlWithoutParams_ = stripParams(this.initialFrameUrl_); 62 this.initialFrameUrlWithoutParams_ = stripParams(this.initialFrameUrl_);
63 this.loaded_ = false;
62 64
63 if (this.desktopMode_) { 65 document.addEventListener('DOMContentLoaded', this.onPageLoad.bind(this));
64 this.supportChannel_ = new Channel();
65 this.supportChannel_.connect('authMain');
66
67 this.supportChannel_.send({
68 name: 'initDesktopFlow',
69 gaiaUrl: this.gaiaUrl_,
70 continueUrl: stripParams(this.continueUrl_),
71 isConstrainedWindow: this.isConstrainedWindow_
72 });
73
74 this.supportChannel_.registerMessage(
75 'switchToFullTab', this.switchToFullTab_.bind(this));
76 this.supportChannel_.registerMessage(
77 'completeLogin', this.completeLogin_.bind(this));
78 }
79
80 document.addEventListener('DOMContentLoaded', this.onPageLoad_.bind(this));
81 document.addEventListener('enableSAML', this.onEnableSAML_.bind(this)); 66 document.addEventListener('enableSAML', this.onEnableSAML_.bind(this));
82 }, 67 },
83 68
84 isGaiaMessage_: function(msg) { 69 isGaiaMessage_: function(msg) {
85 // Not quite right, but good enough. 70 // Not quite right, but good enough.
86 return this.gaiaUrl_.indexOf(msg.origin) == 0 || 71 return this.gaiaUrl_.indexOf(msg.origin) == 0 ||
87 this.GAIA_URL.indexOf(msg.origin) == 0; 72 this.GAIA_URL.indexOf(msg.origin) == 0;
88 }, 73 },
89 74
90 isInternalMessage_: function(msg) { 75 isInternalMessage_: function(msg) {
91 return msg.origin == Authenticator.THIS_EXTENSION_ORIGIN; 76 return msg.origin == Authenticator.THIS_EXTENSION_ORIGIN;
92 }, 77 },
93 78
94 isParentMessage_: function(msg) { 79 isParentMessage_: function(msg) {
95 return msg.origin == this.parentPage_; 80 return msg.origin == this.parentPage_;
96 }, 81 },
97 82
98 constructInitialFrameUrl_: function() { 83 constructInitialFrameUrl_: function() {
99 var url = this.gaiaUrl_ + this.gaiaPath_; 84 var url = this.gaiaUrl_ + this.gaiaPath_;
100 85
101 url = appendParam(url, 'service', this.service_); 86 url = appendParam(url, 'service', this.service_);
102 url = appendParam(url, 'continue', this.continueUrl_); 87 url = appendParam(url, 'continue', this.continueUrl_);
103 if (this.inputLang_) 88 if (this.inputLang_)
104 url = appendParam(url, 'hl', this.inputLang_); 89 url = appendParam(url, 'hl', this.inputLang_);
105 if (this.inputEmail_) 90 if (this.inputEmail_)
106 url = appendParam(url, 'Email', this.inputEmail_); 91 url = appendParam(url, 'Email', this.inputEmail_);
107 if (this.isConstrainedWindow_) 92 if (this.constrained_)
108 url = appendParam(url, 'source', this.CONSTRAINED_FLOW_SOURCE); 93 url = appendParam(url, 'source', this.CONSTRAINED_FLOW_SOURCE);
109 return url; 94 return url;
110 }, 95 },
111 96
112 onPageLoad_: function() { 97 /** Callback when all loads in the gaia webview is complete. */
113 window.addEventListener('message', this.onMessage.bind(this), false); 98 onWebviewLoadstop_: function(gaiaFrame) {
114 this.loadFrame_(); 99 if (gaiaFrame.src.lastIndexOf(this.continueUrlWithoutParams_, 0) == 0) {
100 // Detect when login is finished by the load stop event of the continue
101 // URL. Cannot reuse the login complete flow in success.html, because
102 // webview does not support extension pages yet.
103 var skipForNow = false;
104 if (this.inlineMode_ && gaiaFrame.src.indexOf('ntp=1') >= 0) {
105 skipForNow = true;
106 }
107 msg = {
108 'method': 'completeLogin',
109 'skipForNow': skipForNow
110 };
111 window.parent.postMessage(msg, this.parentPage_);
112 // Do no report state to the parent for the continue URL, since it is a
113 // blank page.
114 return;
115 }
116
117 // Report the current state to the parent which will then update the
118 // browser history so that later it could respond properly to back/forward.
119 var msg = {
120 'method': 'reportState',
121 'src': gaiaFrame.src
122 };
123 window.parent.postMessage(msg, this.parentPage_);
124
125 if (gaiaFrame.src.lastIndexOf(this.gaiaUrl_, 0) == 0) {
126 gaiaFrame.executeScript({file: 'inline_injected.js'}, function() {
127 // Send an initial message to gaia so that it has an JavaScript
128 // reference to the embedder.
129 gaiaFrame.contentWindow.postMessage('', gaiaFrame.src);
130 });
131 if (this.constrained_) {
132 var preventContextMenu = 'document.addEventListener("contextmenu", ' +
133 'function(e) {e.preventDefault();})';
134 gaiaFrame.executeScript({code: preventContextMenu});
135 }
136 }
137
138 this.loaded_ || this.onLoginUILoaded();
139 },
140
141 /**
142 * Callback when the gaia webview attempts to open a new window.
143 */
144 onWebviewNewWindow_: function(gaiaFrame, e) {
145 window.open(e.targetUrl, '_blank');
146 e.window.discard();
147 },
148
149 onWebviewRequestCompleted_: function(details) {
150 if (details.url.lastIndexOf(this.continueUrlWithoutParams_, 0) == 0) {
151 return;
152 }
153
154 var headers = details.responseHeaders;
155 for (var i = 0; headers && i < headers.length; ++i) {
156 if (headers[i].name.toLowerCase() == 'google-accounts-embedded') {
157 return;
158 }
159 }
160 var msg = {
161 'method': 'switchToFullTab',
162 'url': details.url
163 };
164 window.parent.postMessage(msg, this.parentPage_);
115 }, 165 },
116 166
117 loadFrame_: function() { 167 loadFrame_: function() {
118 var gaiaFrame = $('gaia-frame'); 168 var gaiaFrame = $('gaia-frame');
169 gaiaFrame.partition = this.partitionId_;
119 gaiaFrame.src = this.initialFrameUrl_; 170 gaiaFrame.src = this.initialFrameUrl_;
120 if (this.desktopMode_) { 171 if (this.inlineMode_) {
121 var handler = function() { 172 gaiaFrame.addEventListener(
122 this.onLoginUILoaded_(); 173 'loadstop', this.onWebviewLoadstop_.bind(this, gaiaFrame));
123 gaiaFrame.removeEventListener('load', handler); 174 gaiaFrame.addEventListener(
124 }.bind(this); 175 'newwindow', this.onWebviewNewWindow_.bind(this, gaiaFrame));
125 gaiaFrame.addEventListener('load', handler); 176 }
177 if (this.constrained_) {
178 gaiaFrame.request.onCompleted.addListener(
179 this.onWebviewRequestCompleted_.bind(this),
180 {urls: ['<all_urls>'], types: ['main_frame']},
181 ['responseHeaders']);
126 } 182 }
127 }, 183 },
128 184
129 /** 185 completeLogin: function() {
130 * Invoked when the login UI is initialized or reset.
131 */
132 onLoginUILoaded_: function() {
133 var msg = { 186 var msg = {
134 'method': 'loginUILoaded' 187 'method': 'completeLogin',
188 'email': this.email_,
189 'password': this.password_,
190 'usingSAML': this.isSAMLFlow_
135 }; 191 };
136 window.parent.postMessage(msg, this.parentPage_); 192 window.parent.postMessage(msg, this.parentPage_);
193 if (this.samlSupportChannel_)
194 this.samlSupportChannel_.send({name: 'resetAuth'});
137 }, 195 },
138 196
139 /** 197 onPageLoad: function(e) {
140 * Invoked when the background script sends a message to indicate that the 198 window.addEventListener('message', this.onMessage.bind(this), false);
141 * current content does not fit in a constrained window. 199 this.loadFrame_();
142 * @param {Object=} opt_extraMsg Optional extra info to send.
143 */
144 switchToFullTab_: function(msg) {
145 var parentMsg = {
146 'method': 'switchToFullTab',
147 'url': msg.url
148 };
149 window.parent.postMessage(parentMsg, this.parentPage_);
150 },
151
152 /**
153 * Invoked when the signin flow is complete.
154 * @param {Object=} opt_extraMsg Optional extra info to send.
155 */
156 completeLogin_: function(opt_extraMsg) {
157 var msg = {
158 'method': 'completeLogin',
159 'email': (opt_extraMsg && opt_extraMsg.email) || this.email_,
160 'password': this.password_,
161 'usingSAML': this.isSAMLFlow_,
162 'chooseWhatToSync': this.chooseWhatToSync_ || false,
163 'skipForNow': opt_extraMsg && opt_extraMsg.skipForNow,
164 'sessionIndex': opt_extraMsg && opt_extraMsg.sessionIndex
165 };
166 window.parent.postMessage(msg, this.parentPage_);
167 if (this.isSAMLEnabled_)
168 this.supportChannel_.send({name: 'resetAuth'});
169 }, 200 },
170 201
171 /** 202 /**
172 * Invoked when 'enableSAML' event is received to initialize SAML support. 203 * Invoked when 'enableSAML' event is received to initialize SAML support.
173 */ 204 */
174 onEnableSAML_: function() { 205 onEnableSAML_: function() {
175 this.isSAMLEnabled_ = true;
176 this.isSAMLFlow_ = false; 206 this.isSAMLFlow_ = false;
177 207
178 if (!this.supportChannel_) { 208 this.samlSupportChannel_ = new Channel();
179 this.supportChannel_ = new Channel(); 209 this.samlSupportChannel_.connect('authMain');
180 this.supportChannel_.connect('authMain'); 210 this.samlSupportChannel_.registerMessage(
181 }
182
183 this.supportChannel_.registerMessage(
184 'onAuthPageLoaded', this.onAuthPageLoaded_.bind(this)); 211 'onAuthPageLoaded', this.onAuthPageLoaded_.bind(this));
185 this.supportChannel_.registerMessage( 212 this.samlSupportChannel_.registerMessage(
186 'apiCall', this.onAPICall_.bind(this)); 213 'apiCall', this.onAPICall_.bind(this));
187 this.supportChannel_.send({ 214 this.samlSupportChannel_.send({
188 name: 'setGaiaUrl', 215 name: 'setGaiaUrl',
189 gaiaUrl: this.gaiaUrl_ 216 gaiaUrl: this.gaiaUrl_
190 }); 217 });
191 }, 218 },
192 219
193 /** 220 /**
194 * Invoked when the background page sends 'onHostedPageLoaded' message. 221 * Invoked when the background page sends 'onHostedPageLoaded' message.
195 * @param {!Object} msg Details sent with the message. 222 * @param {!Object} msg Details sent with the message.
196 */ 223 */
197 onAuthPageLoaded_: function(msg) { 224 onAuthPageLoaded_: function(msg) {
(...skipping 27 matching lines...) Expand all
225 this.email_ = call.user; 252 this.email_ = call.user;
226 this.password_ = call.password; 253 this.password_ = call.password;
227 } else if (call.method == 'confirm') { 254 } else if (call.method == 'confirm') {
228 if (call.token != this.apiToken_) 255 if (call.token != this.apiToken_)
229 console.error('Authenticator.onAPICall_: token mismatch'); 256 console.error('Authenticator.onAPICall_: token mismatch');
230 } else { 257 } else {
231 console.error('Authenticator.onAPICall_: unknown message'); 258 console.error('Authenticator.onAPICall_: unknown message');
232 } 259 }
233 }, 260 },
234 261
262 onLoginUILoaded: function() {
263 var msg = {
264 'method': 'loginUILoaded'
265 };
266 window.parent.postMessage(msg, this.parentPage_);
267 if (this.inlineMode_) {
268 // TODO(guohui): temporary workaround until webview team fixes the focus
269 // on their side.
270 var gaiaFrame = $('gaia-frame');
271 gaiaFrame.focus();
272 gaiaFrame.onblur = function() {
273 gaiaFrame.focus();
274 };
275 }
276 this.loaded_ = true;
277 },
278
235 onConfirmLogin_: function() { 279 onConfirmLogin_: function() {
236 if (!this.isSAMLFlow_) { 280 if (!this.isSAMLFlow_) {
237 this.completeLogin_(); 281 this.completeLogin();
238 return; 282 return;
239 } 283 }
240 284
241 var apiUsed = !!this.password_; 285 var apiUsed = !!this.password_;
242 286
243 // Retrieve the e-mail address of the user who just authenticated from GAIA. 287 // Retrieve the e-mail address of the user who just authenticated from GAIA.
244 window.parent.postMessage({method: 'retrieveAuthenticatedUserEmail', 288 window.parent.postMessage({method: 'retrieveAuthenticatedUserEmail',
245 attemptToken: this.attemptToken_, 289 attemptToken: this.attemptToken_,
246 apiUsed: apiUsed}, 290 apiUsed: apiUsed},
247 this.parentPage_); 291 this.parentPage_);
248 292
249 if (!apiUsed) { 293 if (!apiUsed) {
250 this.supportChannel_.sendWithCallback( 294 this.samlSupportChannel_.sendWithCallback(
251 {name: 'getScrapedPasswords'}, 295 {name: 'getScrapedPasswords'},
252 function(passwords) { 296 function(passwords) {
253 if (passwords.length == 0) { 297 if (passwords.length == 0) {
254 window.parent.postMessage( 298 window.parent.postMessage(
255 {method: 'noPassword', email: this.email_}, 299 {method: 'noPassword', email: this.email_},
256 this.parentPage_); 300 this.parentPage_);
257 } else { 301 } else {
258 window.parent.postMessage({method: 'confirmPassword', 302 window.parent.postMessage({method: 'confirmPassword',
259 email: this.email_, 303 email: this.email_,
260 passwordCount: passwords.length}, 304 passwordCount: passwords.length},
261 this.parentPage_); 305 this.parentPage_);
262 } 306 }
263 }.bind(this)); 307 }.bind(this));
264 } 308 }
265 }, 309 },
266 310
267 maybeCompleteSAMLLogin_: function() { 311 maybeCompleteSAMLLogin_: function() {
268 // SAML login is complete when the user's e-mail address has been retrieved 312 // SAML login is complete when the user's e-mail address has been retrieved
269 // from GAIA and the user has successfully confirmed the password. 313 // from GAIA and the user has successfully confirmed the password.
270 if (this.email_ !== null && this.password_ !== null) 314 if (this.email_ !== null && this.password_ !== null)
271 this.completeLogin_(); 315 this.completeLogin();
272 }, 316 },
273 317
274 onVerifyConfirmedPassword_: function(password) { 318 onVerifyConfirmedPassword_: function(password) {
275 this.supportChannel_.sendWithCallback( 319 this.samlSupportChannel_.sendWithCallback(
276 {name: 'getScrapedPasswords'}, 320 {name: 'getScrapedPasswords'},
277 function(passwords) { 321 function(passwords) {
278 for (var i = 0; i < passwords.length; ++i) { 322 for (var i = 0; i < passwords.length; ++i) {
279 if (passwords[i] == password) { 323 if (passwords[i] == password) {
280 this.password_ = passwords[i]; 324 this.password_ = passwords[i];
281 this.maybeCompleteSAMLLogin_(); 325 this.maybeCompleteSAMLLogin_();
282 return; 326 return;
283 } 327 }
284 } 328 }
285 window.parent.postMessage( 329 window.parent.postMessage(
286 {method: 'confirmPassword', email: this.email_}, 330 {method: 'confirmPassword', email: this.email_},
287 this.parentPage_); 331 this.parentPage_);
288 }.bind(this)); 332 }.bind(this));
289 }, 333 },
290 334
291 onMessage: function(e) { 335 onMessage: function(e) {
292 var msg = e.data; 336 var msg = e.data;
293 if (msg.method == 'attemptLogin' && this.isGaiaMessage_(e)) { 337 if (msg.method == 'attemptLogin' && this.isGaiaMessage_(e)) {
294 this.email_ = msg.email; 338 this.email_ = msg.email;
295 this.password_ = msg.password; 339 this.password_ = msg.password;
296 this.attemptToken_ = msg.attemptToken; 340 this.attemptToken_ = msg.attemptToken;
297 this.chooseWhatToSync_ = msg.chooseWhatToSync;
298 this.isSAMLFlow_ = false; 341 this.isSAMLFlow_ = false;
299 if (this.isSAMLEnabled_) 342 if (this.samlSupportChannel_)
300 this.supportChannel_.send({name: 'startAuth'}); 343 this.samlSupportChannel_.send({name: 'startAuth'});
301 } else if (msg.method == 'clearOldAttempts' && this.isGaiaMessage_(e)) { 344 } else if (msg.method == 'clearOldAttempts' && this.isGaiaMessage_(e)) {
302 this.email_ = null; 345 this.email_ = null;
303 this.password_ = null; 346 this.password_ = null;
304 this.attemptToken_ = null; 347 this.attemptToken_ = null;
305 this.isSAMLFlow_ = false; 348 this.isSAMLFlow_ = false;
306 this.onLoginUILoaded_(); 349 this.onLoginUILoaded();
307 if (this.isSAMLEnabled_) 350 if (this.samlSupportChannel_)
308 this.supportChannel_.send({name: 'resetAuth'}); 351 this.samlSupportChannel_.send({name: 'resetAuth'});
309 } else if (msg.method == 'setAuthenticatedUserEmail' && 352 } else if (msg.method == 'setAuthenticatedUserEmail' &&
310 this.isParentMessage_(e)) { 353 this.isParentMessage_(e)) {
311 if (this.attemptToken_ == msg.attemptToken) { 354 if (this.attemptToken_ == msg.attemptToken) {
312 this.email_ = msg.email; 355 this.email_ = msg.email;
313 this.maybeCompleteSAMLLogin_(); 356 this.maybeCompleteSAMLLogin_();
314 } 357 }
315 } else if (msg.method == 'confirmLogin' && this.isInternalMessage_(e)) { 358 } else if (msg.method == 'confirmLogin' && this.isInternalMessage_(e)) {
316 if (this.attemptToken_ == msg.attemptToken) 359 if (this.attemptToken_ == msg.attemptToken)
317 this.onConfirmLogin_(); 360 this.onConfirmLogin_();
318 else 361 else
319 console.error('Authenticator.onMessage: unexpected attemptToken!?'); 362 console.error('Authenticator.onMessage: unexpected attemptToken!?');
320 } else if (msg.method == 'verifyConfirmedPassword' && 363 } else if (msg.method == 'verifyConfirmedPassword' &&
321 this.isParentMessage_(e)) { 364 this.isParentMessage_(e)) {
322 this.onVerifyConfirmedPassword_(msg.password); 365 this.onVerifyConfirmedPassword_(msg.password);
323 } else if (msg.method == 'navigate' && 366 } else if (msg.method == 'navigate' &&
324 this.isParentMessage_(e)) { 367 this.isParentMessage_(e)) {
325 $('gaia-frame').src = msg.src; 368 $('gaia-frame').src = msg.src;
326 } else if (msg.method == 'redirectToSignin' && 369 } else if (msg.method == 'redirectToSignin' &&
327 this.isParentMessage_(e)) { 370 this.isParentMessage_(e)) {
328 $('gaia-frame').src = this.constructInitialFrameUrl_(); 371 $('gaia-frame').src = this.constructInitialFrameUrl_();
329 } else { 372 } else {
330 console.error('Authenticator.onMessage: unknown message + origin!?'); 373 console.error('Authenticator.onMessage: unknown message + origin!?');
331 } 374 }
332 } 375 }
333 }; 376 };
334 377
335 Authenticator.getInstance().initialize(); 378 Authenticator.getInstance().initialize();
OLDNEW
« no previous file with comments | « chrome/browser/resources/gaia_auth/inline_main.html ('k') | chrome/browser/resources/gaia_auth/manifest_desktop.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698