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

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

Issue 868203002: Handle authentication failures in the v2 app by restarting the app (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address reviewer's feedback Created 5 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
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 * @fileoverview 6 * @fileoverview
7 * Wrapper class for Chrome's identity API. 7 * Wrapper class for Chrome's identity API.
8 */ 8 */
9 9
10 'use strict'; 10 'use strict';
11 11
12 /** @suppress {duplicate} */ 12 /** @suppress {duplicate} */
13 var remoting = remoting || {}; 13 var remoting = remoting || {};
14 14
15 /** 15 /**
16 * TODO(jamiewalch): Remove remoting.OAuth2 from this type annotation when 16 * TODO(jamiewalch): Remove remoting.OAuth2 from this type annotation when
17 * the Apps v2 work is complete. 17 * the Apps v2 work is complete.
18 * 18 *
19 * @type {remoting.Identity|remoting.OAuth2} 19 * @type {remoting.Identity|remoting.OAuth2}
20 */ 20 */
21 remoting.identity = null; 21 remoting.identity = null;
22 22
23 /** 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 24 * @constructor
28 */ 25 */
29 remoting.Identity = function(consentCallback) { 26 remoting.Identity = function() {
30 /** @private */
31 this.consentCallback_ = consentCallback;
32 /** @type {string} @private */ 27 /** @type {string} @private */
33 this.email_ = ''; 28 this.email_ = '';
34 /** @type {string} @private */ 29 /** @type {string} @private */
35 this.fullName_ = ''; 30 this.fullName_ = '';
36 /** @type {Array.<remoting.Identity.Callbacks>} */ 31 /** @type {Array.<remoting.Identity.Callbacks>} */
37 this.pendingCallbacks_ = []; 32 this.pendingCallbacks_ = [];
33 /** @type {Promise} */
34 this.handleAuthFailurePromise_ = null;
38 }; 35 };
39 36
40 /** 37 /**
41 * Call a function with an access token. 38 * Call a function with an access token.
42 * 39 *
43 * @param {function(string):void} onOk Function to invoke with access token if 40 * @param {function(string):void} onOk Function to invoke with access token if
44 * an access token was successfully retrieved. 41 * an access token was successfully retrieved.
45 * @param {function(remoting.Error):void} onError Function to invoke with an 42 * @param {function(remoting.Error):void} onError Function to invoke with an
46 * error code on failure. 43 * error code on failure.
47 * @return {void} Nothing. 44 * @return {void} Nothing.
(...skipping 20 matching lines...) Expand all
68 /** @type {remoting.Identity} */ 65 /** @type {remoting.Identity} */
69 var that = this; 66 var that = this;
70 67
71 /** 68 /**
72 * @param {string} token 69 * @param {string} token
73 */ 70 */
74 function revokeToken(token) { 71 function revokeToken(token) {
75 chrome.identity.removeCachedAuthToken( 72 chrome.identity.removeCachedAuthToken(
76 {'token': token }, 73 {'token': token },
77 that.callWithToken.bind(that, onOk, onError)); 74 that.callWithToken.bind(that, onOk, onError));
78 }; 75 }
79 76
80 this.callWithToken(revokeToken, onError); 77 this.callWithToken(revokeToken, onError);
81 }; 78 };
82 79
83 /** 80 /**
84 * Remove the cached auth token, if any. 81 * Removes the cached token and prompts the user to get a new one.
85 * 82 * @return {Promise} A promise that resolves when a new token is fetched.
86 * @param {function():void} onDone Completion callback.
87 * @return {void} Nothing.
88 */ 83 */
89 remoting.Identity.prototype.removeCachedAuthToken = function(onDone) { 84 remoting.Identity.prototype.handleAuthFailure = function() {
90 /** @param {string} token */ 85 if (!this.handleAuthFailurePromise_) {
91 var onToken = function(token) { 86 var that = this;
92 if (token) { 87
93 chrome.identity.removeCachedAuthToken({ 'token': token }, onDone); 88 var revokeToken = this.removeCachedAuthToken_();
94 } else { 89
95 onDone(); 90 // Revoke the token.
96 } 91 this.handleAuthFailurePromise_= revokeToken.then(function() {
97 }; 92 // Showing the auth dialog is required as chrome.identity.getAuthToken
98 chrome.identity.getAuthToken({ 'interactive': false }, onToken); 93 // must be initiated from user action when interactive is set to true.
94 return remoting.AuthDialog.show();
95 }).then(function(){
96 // Fetch the new token using the identity API.
97 return base.Promise.as(
98 chrome.identity.getAuthToken, [{ 'interactive': true }]);
99 }).then(
100 /** @param {string} token */
101 function(token) {
102 that.handleAuthFailurePromise_ = null;
103 if (token) {
104 return Promise.resolve(token);
105 }
106 return Promise.reject(remoting.Error.NOT_AUTHENTICATED);
107 }
108 );
109 }
110 return this.handleAuthFailurePromise_;
99 }; 111 };
100 112
101 /** 113 /**
114 * Removes the cached token, prompts the user to get a new one and
115 * relaunches the current window.
116 * @return {void} Nothing.
117 */
118 remoting.Identity.prototype.handleAuthFailureAndRelaunch = function() {
119 this.handleAuthFailure().then(function() {
120 base.IPC.invoke(remoting.ActivationHandler.IPC.RELAUNCH,
kelvinp 2015/01/28 00:26:46 Will be fixed later after I address your feedback
121 chrome.app.window.current().id);
122 });
123 };
124
125 /**
126 * Remove the cached auth token, if any.
127 *
128 * @return {Promise} Promise that resolves when the cached token is removed.
129 * @private
130 */
131 remoting.Identity.prototype.removeCachedAuthToken_ = function() {
132 var getToken =
133 base.Promise.as(chrome.identity.getAuthToken, [{'interactive': false}]);
134 return getToken.then(
135 /** @param {string} token */
136 function(token) {
137 if (token) {
138 return base.Promise.as(chrome.identity.removeCachedAuthToken,
139 [{'token': token}]);
140 } else {
141 return Promise.resolve();
142 }
143 });
144 };
145
146 /**
102 * Get the user's email address and full name. 147 * Get the user's email address and full name.
103 * The full name will be null unless the webapp has requested and been 148 * The full name will be null unless the webapp has requested and been
104 * granted the userinfo.profile permission. 149 * granted the userinfo.profile permission.
105 * 150 *
106 * @param {function(string,string):void} onOk Callback invoked when the user's 151 * @param {function(string,string):void} onOk Callback invoked when the user's
107 * email address and full name are available. 152 * email address and full name are available.
108 * @param {function(remoting.Error):void} onError Callback invoked if an 153 * @param {function(remoting.Error):void} onError Callback invoked if an
109 * error occurs. 154 * error occurs.
110 * @return {void} Nothing. 155 * @return {void} Nothing.
111 */ 156 */
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 console.error(error_message); 244 console.error(error_message);
200 while (this.pendingCallbacks_.length > 0) { 245 while (this.pendingCallbacks_.length > 0) {
201 var callback = /** @type {remoting.Identity.Callbacks} */ 246 var callback = /** @type {remoting.Identity.Callbacks} */
202 (this.pendingCallbacks_.shift()); 247 (this.pendingCallbacks_.shift());
203 callback.onError(remoting.Error.NOT_AUTHENTICATED); 248 callback.onError(remoting.Error.NOT_AUTHENTICATED);
204 } 249 }
205 return; 250 return;
206 } 251 }
207 252
208 // If there's no token, but we haven't yet prompted for permission, do so 253 // If there's no token, but we haven't yet prompted for permission, do so
209 // now. The consent callback is responsible for continuing the auth flow. 254 // now.
210 this.consentCallback_(this.onAuthContinue_.bind(this)); 255 this.handleAuthFailure().then(this.onAuthComplete_.bind(this, true));
211 }; 256 };
212 257
213 /** 258 /**
214 * Called in response to the user signing in to the web-app.
215 *
216 * @private
217 */
218 remoting.Identity.prototype.onAuthContinue_ = function() {
219 chrome.identity.getAuthToken(
220 { 'interactive': true },
221 this.onAuthComplete_.bind(this, true));
222 };
223
224 /**
225 * Internal representation for pair of callWithToken callbacks. 259 * Internal representation for pair of callWithToken callbacks.
226 * 260 *
227 * @param {function(string):void} onOk 261 * @param {function(string):void} onOk
228 * @param {function(remoting.Error):void} onError 262 * @param {function(remoting.Error):void} onError
229 * @constructor 263 * @constructor
230 * @private 264 * @private
231 */ 265 */
232 remoting.Identity.Callbacks = function(onOk, onError) { 266 remoting.Identity.Callbacks = function(onOk, onError) {
233 /** @type {function(string):void} */ 267 /** @type {function(string):void} */
234 this.onOk = onOk; 268 this.onOk = onOk;
235 /** @type {function(remoting.Error):void} */ 269 /** @type {function(remoting.Error):void} */
236 this.onError = onError; 270 this.onError = onError;
237 }; 271 };
238 272
239 /** 273 /**
240 * Returns whether the web app has authenticated with the Google services. 274 * Returns whether the web app has authenticated with the Google services.
241 * 275 *
242 * @return {boolean} 276 * @return {boolean}
243 */ 277 */
244 remoting.Identity.prototype.isAuthenticated = function() { 278 remoting.Identity.prototype.isAuthenticated = function() {
245 return remoting.identity.email_ !== ''; 279 return remoting.identity.email_ !== '';
246 }; 280 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698