ozone: evdev: Sync caps lock LED state to evdev
[chromium-blink-merge.git] / chrome / browser / resources / gaia_auth_host / gaia_auth_host.js
blob7cef0cfecaee26c4259a833d662c3a8f83497e15
1 // Copyright 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.
5 /**
6 * @fileoverview An UI component to host gaia auth extension in an iframe.
7 * After the component binds with an iframe, call its {@code load} to start the
8 * authentication flow. There are two events would be raised after this point:
9 * a 'ready' event when the authentication UI is ready to use and a 'completed'
10 * event when the authentication is completed successfully. If caller is
11 * interested in the user credentials, he may supply a success callback with
12 * {@code load} call. The callback will be invoked when the authentication is
13 * completed successfully and with the available credential data.
16 cr.define('cr.login', function() {
17 'use strict';
19 /**
20 * Base URL of gaia auth extension.
21 * @const
23 var AUTH_URL_BASE = 'chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik';
25 /**
26 * Auth URL to use for online flow.
27 * @const
29 var AUTH_URL = AUTH_URL_BASE + '/main.html';
31 /**
32 * Auth URL to use for offline flow.
33 * @const
35 var OFFLINE_AUTH_URL = AUTH_URL_BASE + '/offline.html';
37 /**
38 * Origin of the gaia sign in page.
39 * @const
41 var GAIA_ORIGIN = 'https://accounts.google.com';
43 /**
44 * Supported params of auth extension. For a complete list, check out the
45 * auth extension's main.js.
46 * @type {!Array<string>}
47 * @const
49 var SUPPORTED_PARAMS = [
50 'gaiaUrl', // Gaia url to use;
51 'gaiaPath', // Gaia path to use without a leading slash;
52 'hl', // Language code for the user interface;
53 'email', // Pre-fill the email field in Gaia UI;
54 'service', // Name of Gaia service;
55 'continueUrl', // Continue url to use;
56 'frameUrl', // Initial frame URL to use. If empty defaults to gaiaUrl.
57 'constrained' // Whether the extension is loaded in a constrained window;
60 /**
61 * Supported localized strings. For a complete list, check out the auth
62 * extension's offline.js
63 * @type {!Array<string>}
64 * @const
66 var LOCALIZED_STRING_PARAMS = [
67 'stringSignIn',
68 'stringEmail',
69 'stringPassword',
70 'stringEmptyEmail',
71 'stringEmptyPassword',
72 'stringError'
75 /**
76 * Enum for the authorization mode, must match AuthMode defined in
77 * chrome/browser/ui/webui/inline_login_ui.cc.
78 * @enum {number}
80 var AuthMode = {
81 DEFAULT: 0,
82 OFFLINE: 1,
83 DESKTOP: 2
86 /**
87 * Enum for the auth flow.
88 * @enum {number}
90 var AuthFlow = {
91 GAIA: 0,
92 SAML: 1
95 /**
96 * Creates a new gaia auth extension host.
97 * @param {HTMLIFrameElement|string} container The iframe element or its id
98 * to host the auth extension.
99 * @constructor
100 * @extends {cr.EventTarget}
102 function GaiaAuthHost(container) {
103 this.frame_ = typeof container == 'string' ? $(container) : container;
104 assert(this.frame_);
105 window.addEventListener('message',
106 this.onMessage_.bind(this), false);
109 GaiaAuthHost.prototype = {
110 __proto__: cr.EventTarget.prototype,
113 * Auth extension params
114 * @type {Object}
116 authParams_: {},
119 * An url to use with {@code reload}.
120 * @type {?string}
121 * @private
123 reloadUrl_: null,
126 * The domain name of the current auth page.
127 * @type {string}
129 authDomain: '',
132 * Invoked when authentication is completed successfully with credential
133 * data. A credential data object looks like this:
134 * <pre>
135 * {@code
137 * email: 'xx@gmail.com',
138 * password: 'xxxx', // May not present
139 * authCode: 'x/xx', // May not present
140 * authMode: 'x', // Authorization mode, default/offline/desktop.
143 * </pre>
144 * @type {function(Object)}
145 * @private
147 successCallback_: null,
150 * Invoked when the auth flow needs a user to confirm his/her passwords.
151 * This could happen when there are more than one passwords scraped during
152 * SAML flow. The embedder of GaiaAuthHost should show an UI to collect a
153 * password from user then call GaiaAuthHost.verifyConfirmedPassword to
154 * verify. If the password is good, the auth flow continues with success
155 * path. Otherwise, confirmPasswordCallback_ is invoked again.
156 * @type {function()}
158 confirmPasswordCallback_: null,
161 * Similar to confirmPasswordCallback_ but is used when there is no
162 * password scraped after a success authentication. The authenticated user
163 * account is passed to the callback. The embedder should take over the
164 * flow and decide what to do next.
165 * @type {function(string)}
167 noPasswordCallback_: null,
170 * Invoked when the authentication flow had to be aborted because content
171 * served over an unencrypted connection was detected.
173 insecureContentBlockedCallback_: null,
176 * Invoked to display an error message to the user when a GAIA error occurs
177 * during authentication.
178 * @type {function()}
180 missingGaiaInfoCallback_: null,
183 * Invoked to record that the credentials passing API was used.
184 * @type {function()}
186 samlApiUsedCallback_: null,
189 * The iframe container.
190 * @type {HTMLIFrameElement}
192 get frame() {
193 return this.frame_;
197 * Sets confirmPasswordCallback_.
198 * @type {function()}
200 set confirmPasswordCallback(callback) {
201 this.confirmPasswordCallback_ = callback;
205 * Sets noPasswordCallback_.
206 * @type {function()}
208 set noPasswordCallback(callback) {
209 this.noPasswordCallback_ = callback;
213 * Sets insecureContentBlockedCallback_.
214 * @type {function(string)}
216 set insecureContentBlockedCallback(callback) {
217 this.insecureContentBlockedCallback_ = callback;
221 * Sets missingGaiaInfoCallback_.
222 * @type {function()}
224 set missingGaiaInfoCallback(callback) {
225 this.missingGaiaInfoCallback_ = callback;
229 * Sets samlApiUsedCallback_.
230 * @type {function()}
232 set samlApiUsedCallback(callback) {
233 this.samlApiUsedCallback_ = callback;
237 * Loads the auth extension.
238 * @param {AuthMode} authMode Authorization mode.
239 * @param {Object} data Parameters for the auth extension. See the auth
240 * extension's main.js for all supported params and their defaults.
241 * @param {function(Object)} successCallback A function to be called when
242 * the authentication is completed successfully. The callback is
243 * invoked with a credential object.
245 load: function(authMode, data, successCallback) {
246 var params = {};
248 var populateParams = function(nameList, values) {
249 if (!values)
250 return;
252 for (var i in nameList) {
253 var name = nameList[i];
254 if (values[name])
255 params[name] = values[name];
259 populateParams(SUPPORTED_PARAMS, data);
260 populateParams(LOCALIZED_STRING_PARAMS, data.localizedStrings);
261 params['needPassword'] = true;
263 var url;
264 switch (authMode) {
265 case AuthMode.OFFLINE:
266 url = OFFLINE_AUTH_URL;
267 break;
268 case AuthMode.DESKTOP:
269 url = AUTH_URL;
270 params['desktopMode'] = true;
271 break;
272 default:
273 url = AUTH_URL;
276 this.authParams_ = params;
277 this.reloadUrl_ = url;
278 this.successCallback_ = successCallback;
280 this.reload();
284 * Reloads the auth extension.
286 reload: function() {
287 var sendParamsOnLoad = function() {
288 this.frame_.removeEventListener('load', sendParamsOnLoad);
289 this.frame_.contentWindow.postMessage(this.authParams_, AUTH_URL_BASE);
290 }.bind(this);
292 this.frame_.addEventListener('load', sendParamsOnLoad);
293 this.frame_.src = this.reloadUrl_;
294 this.authFlow = AuthFlow.GAIA;
298 * Verifies the supplied password by sending it to the auth extension,
299 * which will then check if it matches the scraped passwords.
300 * @param {string} password The confirmed password that needs verification.
302 verifyConfirmedPassword: function(password) {
303 var msg = {
304 method: 'verifyConfirmedPassword',
305 password: password
307 this.frame_.contentWindow.postMessage(msg, AUTH_URL_BASE);
311 * Invoked to process authentication success.
312 * @param {Object} credentials Credential object to pass to success
313 * callback.
314 * @private
316 onAuthSuccess_: function(credentials) {
317 if (this.successCallback_)
318 this.successCallback_(credentials);
319 cr.dispatchSimpleEvent(this, 'completed');
323 * Checks if message comes from the loaded authentication extension.
324 * @param {Object} e Payload of the received HTML5 message.
325 * @type {boolean}
327 isAuthExtMessage_: function(e) {
328 return this.frame_.src &&
329 this.frame_.src.indexOf(e.origin) == 0 &&
330 e.source == this.frame_.contentWindow;
334 * Event handler that is invoked when HTML5 message is received.
335 * @param {object} e Payload of the received HTML5 message.
337 onMessage_: function(e) {
338 var msg = e.data;
340 if (!this.isAuthExtMessage_(e))
341 return;
343 if (msg.method == 'loginUILoaded') {
344 cr.dispatchSimpleEvent(this, 'ready');
345 return;
348 if (/^complete(Login|Authentication)$|^offlineLogin$/.test(msg.method)) {
349 if (!msg.email && !this.email_ && !msg.skipForNow) {
350 var msg = {method: 'redirectToSignin'};
351 this.frame_.contentWindow.postMessage(msg, AUTH_URL_BASE);
352 return;
354 this.onAuthSuccess_({email: msg.email,
355 password: msg.password,
356 gaiaId: msg.gaiaId,
357 useOffline: msg.method == 'offlineLogin',
358 usingSAML: msg.usingSAML || false,
359 chooseWhatToSync: msg.chooseWhatToSync,
360 skipForNow: msg.skipForNow || false,
361 sessionIndex: msg.sessionIndex || ''});
362 return;
365 if (msg.method == 'confirmPassword') {
366 if (this.confirmPasswordCallback_)
367 this.confirmPasswordCallback_(msg.passwordCount);
368 else
369 console.error('GaiaAuthHost: Invalid confirmPasswordCallback_.');
370 return;
373 if (msg.method == 'noPassword') {
374 if (this.noPasswordCallback_)
375 this.noPasswordCallback_(msg.email);
376 else
377 console.error('GaiaAuthHost: Invalid noPasswordCallback_.');
378 return;
381 if (msg.method == 'authPageLoaded') {
382 this.authDomain = msg.domain;
383 this.authFlow = msg.isSAML ? AuthFlow.SAML : AuthFlow.GAIA;
384 return;
387 if (msg.method == 'resetAuthFlow') {
388 this.authFlow = AuthFlow.GAIA;
389 return;
392 if (msg.method == 'insecureContentBlocked') {
393 if (this.insecureContentBlockedCallback_) {
394 this.insecureContentBlockedCallback_(msg.url);
395 } else {
396 console.error(
397 'GaiaAuthHost: Invalid insecureContentBlockedCallback_.');
399 return;
402 if (msg.method == 'switchToFullTab') {
403 chrome.send('switchToFullTab', [msg.url]);
404 return;
407 if (msg.method == 'missingGaiaInfo') {
408 if (this.missingGaiaInfoCallback_) {
409 this.missingGaiaInfoCallback_();
410 } else {
411 console.error('GaiaAuthHost: Invalid missingGaiaInfoCallback_.');
413 return;
416 if (msg.method == 'samlApiUsed') {
417 if (this.samlApiUsedCallback_) {
418 this.samlApiUsedCallback_();
419 } else {
420 console.error('GaiaAuthHost: Invalid samlApiUsedCallback_.');
422 return;
425 console.error('Unknown message method=' + msg.method);
430 * The current auth flow of the hosted gaia_auth extension.
431 * @type {AuthFlow}
433 cr.defineProperty(GaiaAuthHost, 'authFlow');
435 GaiaAuthHost.SUPPORTED_PARAMS = SUPPORTED_PARAMS;
436 GaiaAuthHost.LOCALIZED_STRING_PARAMS = LOCALIZED_STRING_PARAMS;
437 GaiaAuthHost.AuthMode = AuthMode;
438 GaiaAuthHost.AuthFlow = AuthFlow;
440 return {
441 GaiaAuthHost: GaiaAuthHost