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

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: Removed identity.js from html. Fixed patch. 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
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 the remoting.OAuth2 possibility when the Apps v2
Wez 2013/01/05 00:04:24 nit: "the" and "possibility" are redundant here.
Jamie 2013/01/05 01:32:54 Done.
17 * work is complete.
18 *
19 * @type {remoting.Identity|remoting.OAuth2}
20 */
21 remoting.identity = null;
22
23
24 /**
25 * @param {HTMLElement} authDialog The authentication dialog, to be displayed
26 * if user permission is required to obtain an access token.
27 * @param {HTMLElement} authButton The "Continue" button, which must be a
28 * visible child of the dialog.
29 * @constructor
30 */
31 remoting.Identity = function(authDialog, authButton) {
Wez 2013/01/05 00:04:24 This arrangement is a little strange; this class s
Jamie 2013/01/05 01:32:54 Done.
32 /** @private */
33 this.dialog_ = authDialog;
34 /** @type {?string} @private */
35 this.email_ = null;
36 /** @type {Array.<remoting.Identity.Callbacks>} */
37 this.pendingCallbacks_ = [];
38 authButton.addEventListener('click', this.onAuthContinue_.bind(this), false);
39 };
40
41 /**
42 * Call a function with an access token.
43 *
44 * @param {function(string):void} onOk Function to invoke with access token if
45 * an access token was successfully retrieved.
46 * @param {function(remoting.Error):void} onError Function to invoke with an
47 * error code on failure.
48 * @return {void} Nothing.
49 */
50 remoting.Identity.prototype.callWithToken = function(onOk, onError) {
51 this.pendingCallbacks_.push(new remoting.Identity.Callbacks(onOk, onError));
52 if (this.pendingCallbacks_.length == 1) {
53 chrome.experimental.identity.getAuthToken(
54 { 'interactive': false },
55 this.onAuthComplete_.bind(this, false));
56 }
57 };
58
59 /**
60 * Get the user's email address.
61 *
62 * @param {function(string):void} onOk Callback invoked when the email
63 * address is available.
64 * @param {function(remoting.Error):void} onError Callback invoked if an
65 * error occurs.
66 * @return {void} Nothing.
67 */
68 remoting.Identity.prototype.getEmail = function(onOk, onError) {
69 /** @type {remoting.Identity} */
70 var that = this;
71 /** @param {XMLHttpRequest} xhr The XHR response. */
72 var onResponse = function(xhr) {
73 var email = null;
74 if (xhr.status == 200) {
75 // TODO(ajwong): See if we can't find a JSON endpoint.
Wez 2013/01/05 00:04:24 What does this TODO mean?
Jamie 2013/01/05 01:32:54 It's essentially the same as the next TODO. I've r
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.
Wez 2013/01/05 00:04:24 Does this mean use a new v2 Google API, or use an
Jamie 2013/01/05 01:32:54 There's an endpoint, https://www.googleapis.com/oa
Wez 2013/01/07 23:52:44 OK, great - can you create a bug for migrating to
Jamie 2013/01/08 22:09:10 I think Renato is in the process of fixing it as w
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.
Wez 2013/01/05 00:04:24 nit: Worth noting that this may return a valid ema
Jamie 2013/01/05 01:32:54 I don't think that would add much.
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
138 * @param {?string} token
139 * @private
140 */
141 remoting.Identity.prototype.onAuthComplete_ = function(interactive, token) {
Wez 2013/01/05 00:04:24 nit: interactive -> was_interactive?
Jamie 2013/01/05 01:32:54 I've left this as it was, but added some descripti
142 // Pass the token to the callback(s) if it was retrieved successfully.
143 if (token) {
144 for (var i = 0; i < this.pendingCallbacks_.length; ++i) {
145 this.pendingCallbacks_[i].onOk(token);
Wez 2013/01/05 00:04:24 nit: Can you re-write this as a while(!empty) loop
Jamie 2013/01/05 01:32:54 Done, and also below.
146 }
147 this.pendingCallbacks_ = [];
148 return;
149 }
150
151 // If not, pass an error back to the callback(s) if we've already prompted the
152 // user for permission.
153 // TODO(jamiewalch): Figure out what to do with the error in this case.
154 if (interactive) {
155 console.error(chrome.runtime.lastError);
156 for (var i = 0; i < this.pendingCallbacks_.length; ++i) {
157 this.pendingCallbacks_[i].onError(remoting.Error.UNEXPECTED);
158 }
159 this.pendingCallbacks_ = [];
160 return;
161 }
162
163 // If there's no token, but we haven't yet prompted for permission, do so
164 // now. The flow will continue via the Continue button event handler.
165 this.dialog_.hidden = false;
166 };
167
168 /**
169 * Called in response to the user signing in to the web-app.
170 *
171 * @private
172 */
173 remoting.Identity.prototype.onAuthContinue_ = function() {
174 this.dialog_.hidden = true;
175 chrome.experimental.identity.getAuthToken(
176 { 'interactive': true },
177 this.onAuthComplete_.bind(this, true));
178 };
179
180 /**
181 * Internal representation for pair of callWithToken callbacks.
182 *
183 * @param {function(string):void} onOk
184 * @param {function(remoting.Error):void} onError
185 * @constructor
186 * @private
187 */
188 remoting.Identity.Callbacks = function(onOk, onError) {
189 /** @type {function(string):void} */
190 this.onOk = onOk;
191 /** @type {function(remoting.Error):void} */
192 this.onError = onError;
193 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698