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

Side by Side Diff: remoting/webapp/identity.js

Issue 11769002: Apps v2 identity integration. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase Created 7 years, 11 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
« no previous file with comments | « remoting/webapp/host_setup_dialog.js ('k') | remoting/webapp/jscompiler_hacks.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 /**
6 * @fileoverview
7 * Wrapper class for Chrome's identity API.
8 */
9
10 'use strict';
11
12 /** @suppress {duplicate} */
13 var remoting = remoting || {};
14
15 /**
16 * TODO(jamiewalch): Remove remoting.OAuth2 from this type annotation when
17 * the Apps v2 work is complete.
18 *
19 * @type {remoting.Identity|remoting.OAuth2}
20 */
21 remoting.identity = null;
22
23 /**
24 * @param {function(function():void):void} consentCallback Callback invoked if
25 * user consent is required. The callback is passed a continuation function
26 * which must be called from an interactive event handler (e.g. "click").
27 * @constructor
28 */
29 remoting.Identity = function(consentCallback) {
30 /** @private */
31 this.consentCallback_ = consentCallback;
32 /** @type {?string} @private */
33 this.email_ = null;
34 /** @type {Array.<remoting.Identity.Callbacks>} */
35 this.pendingCallbacks_ = [];
36 };
37
38 /**
39 * Call a function with an access token.
40 *
41 * TODO(jamiewalch): Currently, this results in a new GAIA token being minted
42 * each time the function is called. Implement caching functionality unless
43 * getAuthToken starts doing so itself.
Wez 2013/01/09 23:47:24 Can you create a bug for resolving this one way or
44 *
45 * @param {function(string):void} onOk Function to invoke with access token if
46 * an access token was successfully retrieved.
47 * @param {function(remoting.Error):void} onError Function to invoke with an
48 * error code on failure.
49 * @return {void} Nothing.
50 */
51 remoting.Identity.prototype.callWithToken = function(onOk, onError) {
52 this.pendingCallbacks_.push(new remoting.Identity.Callbacks(onOk, onError));
53 if (this.pendingCallbacks_.length == 1) {
54 chrome.experimental.identity.getAuthToken(
55 { 'interactive': false },
56 this.onAuthComplete_.bind(this, false));
57 }
58 };
59
60 /**
61 * Get the user's email address.
62 *
63 * @param {function(string):void} onOk Callback invoked when the email
64 * address is available.
65 * @param {function(remoting.Error):void} onError Callback invoked if an
66 * error occurs.
67 * @return {void} Nothing.
68 */
69 remoting.Identity.prototype.getEmail = function(onOk, onError) {
70 /** @type {remoting.Identity} */
71 var that = this;
72 /** @param {XMLHttpRequest} xhr The XHR response. */
73 var onResponse = function(xhr) {
74 var email = null;
75 if (xhr.status == 200) {
76 email = xhr.responseText.split('&')[0].split('=')[1];
77 that.email_ = email;
78 onOk(email);
79 return;
80 }
81 console.error('Unable to get email address:', xhr.status, xhr);
82 if (xhr.status == 401) {
83 onError(remoting.Error.AUTHENTICATION_FAILED);
84 } else {
85 onError(that.interpretUnexpectedXhrStatus_(xhr.status));
86 }
87 };
88
89 /** @param {string} token The access token. */
90 var getEmailFromToken = function(token) {
91 var headers = { 'Authorization': 'OAuth ' + token };
92 // TODO(ajwong): Update to new v2 API.
93 remoting.xhr.get('https://www.googleapis.com/userinfo/email',
94 onResponse, '', headers);
95 };
96
97 this.callWithToken(getEmailFromToken, onError);
98 };
99
100 /**
101 * Get the user's email address, or null if no successful call to getEmail
102 * has been made.
103 *
104 * @return {?string} The cached email address, if available.
105 */
106 remoting.Identity.prototype.getCachedEmail = function() {
107 return this.email_;
108 };
109
110 /**
111 * Interprets unexpected HTTP response codes to authentication XMLHttpRequests.
112 * The caller should handle the usual expected responses (200, 400) separately.
113 *
114 * @param {number} xhrStatus Status (HTTP response code) of the XMLHttpRequest.
115 * @return {remoting.Error} An error code to be raised.
116 * @private
117 */
118 remoting.Identity.prototype.interpretUnexpectedXhrStatus_ = function(
119 xhrStatus) {
120 // Return AUTHENTICATION_FAILED by default, so that the user can try to
121 // recover from an unexpected failure by signing in again.
122 /** @type {remoting.Error} */
123 var error = remoting.Error.AUTHENTICATION_FAILED;
124 if (xhrStatus == 502 || xhrStatus == 503) {
125 error = remoting.Error.SERVICE_UNAVAILABLE;
126 } else if (xhrStatus == 0) {
127 error = remoting.Error.NETWORK_FAILURE;
128 } else {
129 console.warn('Unexpected authentication response code: ' + xhrStatus);
130 }
131 return error;
132 };
133
134 /**
135 * Callback for the getAuthToken API.
136 *
137 * @param {boolean} interactive The value of the "interactive" parameter to
138 * getAuthToken.
139 * @param {?string} token The auth token, or null if the request failed.
140 * @private
141 */
142 remoting.Identity.prototype.onAuthComplete_ = function(interactive, token) {
143 // Pass the token to the callback(s) if it was retrieved successfully.
144 if (token) {
145 while (this.pendingCallbacks_.length > 0) {
146 var callback = /** @type {remoting.Identity.Callbacks} */
147 this.pendingCallbacks_.shift();
148 callback.onOk(token);
149 }
150 return;
151 }
152
153 // If not, pass an error back to the callback(s) if we've already prompted the
154 // user for permission.
155 // TODO(jamiewalch): Figure out what to do with the error in this case.
156 if (interactive) {
157 console.error(chrome.runtime.lastError);
158 while (this.pendingCallbacks_.length > 0) {
159 var callback = /** @type {remoting.Identity.Callbacks} */
160 this.pendingCallbacks_.shift();
161 callback.onError(remoting.Error.UNEXPECTED);
162 }
163 return;
164 }
165
166 // If there's no token, but we haven't yet prompted for permission, do so
167 // now. The consent callback is responsible for continuing the auth flow.
168 this.consentCallback_(this.onAuthContinue_.bind(this));
169 };
170
171 /**
172 * Called in response to the user signing in to the web-app.
173 *
174 * @private
175 */
176 remoting.Identity.prototype.onAuthContinue_ = function() {
177 chrome.experimental.identity.getAuthToken(
178 { 'interactive': true },
179 this.onAuthComplete_.bind(this, true));
180 };
181
182 /**
183 * Internal representation for pair of callWithToken callbacks.
184 *
185 * @param {function(string):void} onOk
186 * @param {function(remoting.Error):void} onError
187 * @constructor
188 * @private
189 */
190 remoting.Identity.Callbacks = function(onOk, onError) {
191 /** @type {function(string):void} */
192 this.onOk = onOk;
193 /** @type {function(remoting.Error):void} */
194 this.onError = onError;
195 };
OLDNEW
« no previous file with comments | « remoting/webapp/host_setup_dialog.js ('k') | remoting/webapp/jscompiler_hacks.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698