Index: remoting/webapp/crd/js/identity.js |
diff --git a/remoting/webapp/crd/js/identity.js b/remoting/webapp/crd/js/identity.js |
index 161e083e318069d929c937062d2f39fdf102e469..0ae2dbf457a9f890c4a74adc70116bd895ff7063 100644 |
--- a/remoting/webapp/crd/js/identity.js |
+++ b/remoting/webapp/crd/js/identity.js |
@@ -31,8 +31,8 @@ remoting.Identity = function(opt_consentDialog) { |
this.email_ = ''; |
/** @type {string} @private */ |
this.fullName_ = ''; |
- /** @type {Array.<remoting.Identity.Callbacks>} */ |
- this.pendingCallbacks_ = []; |
+ /** @type {Promise<string>} */ |
+ this.pendingPromise_ = null; |
}; |
/** |
@@ -51,117 +51,118 @@ remoting.Identity.ConsentDialog = function() {}; |
remoting.Identity.ConsentDialog.prototype.show = function() {}; |
/** |
- * Call a function with an access token. |
+ * Get an access token. |
* |
- * @param {function(string):void} onOk Function to invoke with access token if |
- * an access token was successfully retrieved. |
- * @param {function(remoting.Error):void} onError Function to invoke with an |
- * error code on failure. |
- * @return {void} Nothing. |
+ * @return {!Promise<string>} A promise resolved the an access token or |
+ * rejected with a remoting.Error. |
*/ |
-remoting.Identity.prototype.callWithToken = function(onOk, onError) { |
- this.pendingCallbacks_.push(new remoting.Identity.Callbacks(onOk, onError)); |
- if (this.pendingCallbacks_.length == 1) { |
- chrome.identity.getAuthToken( |
- { 'interactive': false }, |
- this.onAuthComplete_.bind(this, false)); |
+remoting.Identity.prototype.getToken = function() { |
+ /** @const */ |
+ var that = this; |
+ |
+ if (this.pendingPromise_ == null) { |
+ this.pendingPromise_ = new Promise(function( |
kelvinp
2015/02/18 19:45:24
I think base.Deferred will work better as you want
John Williams
2015/02/18 20:28:22
Done.
|
+ /** function(string) */ resolve, |
kelvinp
2015/02/18 19:45:24
Is this a new syntax of annotating parameters? I l
John Williams
2015/02/18 20:28:22
It's a recent addition to the syntax. I like it f
|
+ /** function(remoting.Error) */ reject) { |
+ chrome.identity.getAuthToken( |
+ { 'interactive': false }, |
+ that.onAuthComplete_.bind(that, resolve, reject, false)); |
+ }); |
} |
+ return this.pendingPromise_; |
}; |
/** |
- * Call a function with a fresh access token. |
+ * Get a fresh access token. |
kelvinp
2015/02/18 19:45:24
Nit: Gets
John Williams
2015/02/18 20:28:22
Done.
|
* |
- * @param {function(string):void} onOk Function to invoke with access token if |
- * an access token was successfully retrieved. |
- * @param {function(remoting.Error):void} onError Function to invoke with an |
- * error code on failure. |
- * @return {void} Nothing. |
+ * @return {!Promise<string>} A promise resolved the an access token or |
kelvinp
2015/02/18 19:45:24
s/resolved the an/resolved with an/
|
+ * rejected with a remoting.Error. |
*/ |
-remoting.Identity.prototype.callWithNewToken = function(onOk, onError) { |
+remoting.Identity.prototype.getNewToken = function() { |
/** @type {remoting.Identity} */ |
var that = this; |
- /** |
- * @param {string} token |
- */ |
- function revokeToken(token) { |
- chrome.identity.removeCachedAuthToken( |
- {'token': token }, |
- that.callWithToken.bind(that, onOk, onError)); |
- } |
- |
- this.callWithToken(revokeToken, onError); |
+ return this.getToken().then(function(/** string */ token) { |
+ return new Promise(function(resolve, reject) { |
+ chrome.identity.removeCachedAuthToken({'token': token }, function() { |
+ resolve(that.getToken()); |
+ }); |
+ }); |
+ }); |
}; |
/** |
* Remove the cached auth token, if any. |
* |
- * @param {function():void=} opt_onDone Completion callback. |
- * @return {void} Nothing. |
+ * @return {!Promise<null>} A promise resolved with the operation completes. |
*/ |
-remoting.Identity.prototype.removeCachedAuthToken = function(opt_onDone) { |
- var onDone = (opt_onDone) ? opt_onDone : base.doNothing; |
- |
- /** @param {string} token */ |
- var onToken = function(token) { |
- if (token) { |
- chrome.identity.removeCachedAuthToken({'token': token}, onDone); |
- } else { |
- onDone(); |
- } |
- }; |
- chrome.identity.getAuthToken({'interactive': false}, onToken); |
+remoting.Identity.prototype.removeCachedAuthToken = function() { |
+ return new Promise(function(resolve, reject) { |
+ /** @param {string} token */ |
+ var onToken = function(token) { |
+ if (token) { |
+ chrome.identity.removeCachedAuthToken( |
+ {'token': token}, resolve.bind(null, null)); |
+ } else { |
+ resolve(null); |
+ } |
+ }; |
+ chrome.identity.getAuthToken({'interactive': false}, onToken); |
+ }); |
}; |
/** |
- * Get the user's email address and full name. |
- * The full name will be null unless the webapp has requested and been |
- * granted the userinfo.profile permission. |
+ * Get the user's email address and full name. The full name will be |
+ * null unless the webapp has requested and been granted the |
+ * userinfo.profile permission. |
+ * |
+ * TODO(jrw): Type declarations say the name can't be null. Are the |
+ * types wrong, or is the documentation wrong? |
* |
- * @param {function(string,string):void} onOk Callback invoked when the user's |
- * email address and full name are available. |
- * @param {function(remoting.Error):void} onError Callback invoked if an |
- * error occurs. |
- * @return {void} Nothing. |
+ * @return {!Promise<{email: string, name: string}>} Promise |
kelvinp
2015/02/18 19:45:24
no space between : and type name
John Williams
2015/02/18 20:28:22
Done.
|
+ * resolved with the user's email address and full name, or rejected |
+ * with a remoting.Error. |
*/ |
-remoting.Identity.prototype.getUserInfo = function(onOk, onError) { |
+remoting.Identity.prototype.getUserInfo = function() { |
if (this.isAuthenticated()) { |
- onOk(this.email_, this.fullName_); |
- return; |
+ /** |
+ * The temp variable is needed to work around a compiler bug. |
+ * @type {{email: string, name: string}} |
+ */ |
+ var result = {email: this.email_, name: this.fullName_}; |
+ return Promise.resolve(result); |
} |
/** @type {remoting.Identity} */ |
var that = this; |
- /** |
- * @param {string} email |
- * @param {string} name |
- */ |
- var onResponse = function(email, name) { |
- that.email_ = email; |
- that.fullName_ = name; |
- onOk(email, name); |
- }; |
- |
- this.callWithToken( |
- remoting.oauth2Api.getUserInfo.bind( |
- remoting.oauth2Api, onResponse, onError), |
- onError); |
+ return this.getToken().then(function(token) { |
+ return new Promise(function(resolve, reject) { |
+ /** |
+ * @param {string} email |
+ * @param {string} name |
+ */ |
+ var onResponse = function(email, name) { |
+ that.email_ = email; |
+ that.fullName_ = name; |
+ resolve({email: email, name: name}); |
+ }; |
+ |
+ remoting.oauth2Api.getUserInfo(onResponse, reject, token); |
+ }); |
+ }); |
}; |
/** |
* Get the user's email address. |
* |
- * @param {function(string):void} onOk Callback invoked when the email |
- * address is available. |
- * @param {function(remoting.Error):void} onError Callback invoked if an |
- * error occurs. |
- * @return {void} Nothing. |
+ * @return {!Promise<string>} Promise resolved with the user's email |
+ * address or rejected with a remoting.Error. |
*/ |
-remoting.Identity.prototype.getEmail = function(onOk, onError) { |
- this.getUserInfo(function(email, name) { |
- onOk(email); |
- }, onError); |
+remoting.Identity.prototype.getEmail = function() { |
+ this.getUserInfo().then(function(userInfo) { |
+ return userInfo.email; |
+ }); |
}; |
/** |
@@ -189,19 +190,19 @@ remoting.Identity.prototype.getCachedUserFullName = function() { |
/** |
* Callback for the getAuthToken API. |
* |
+ * @param {function(string):void} resolve |
+ * @param {function(remoting.Error):void} reject |
* @param {boolean} interactive The value of the "interactive" parameter to |
* getAuthToken. |
* @param {?string} token The auth token, or null if the request failed. |
* @private |
*/ |
-remoting.Identity.prototype.onAuthComplete_ = function(interactive, token) { |
+remoting.Identity.prototype.onAuthComplete_ = function( |
+ resolve, reject, interactive, token) { |
kelvinp
2015/02/18 19:45:24
As commented earlier, use base.Deferred instead
John Williams
2015/02/18 20:28:22
Done.
|
// Pass the token to the callback(s) if it was retrieved successfully. |
if (token) { |
- while (this.pendingCallbacks_.length > 0) { |
- var callback = /** @type {remoting.Identity.Callbacks} */ |
- (this.pendingCallbacks_.shift()); |
- callback.onOk(token); |
- } |
+ resolve(token); |
+ this.pendingPromise_ = null; |
return; |
} |
@@ -212,11 +213,7 @@ remoting.Identity.prototype.onAuthComplete_ = function(interactive, token) { |
chrome.runtime.lastError ? chrome.runtime.lastError.message |
: 'Unknown error.'; |
console.error(error_message); |
- while (this.pendingCallbacks_.length > 0) { |
- var callback = /** @type {remoting.Identity.Callbacks} */ |
- (this.pendingCallbacks_.shift()); |
- callback.onError(remoting.Error.NOT_AUTHENTICATED); |
- } |
+ reject(remoting.Error.NOT_AUTHENTICATED); |
return; |
} |
@@ -227,26 +224,12 @@ remoting.Identity.prototype.onAuthComplete_ = function(interactive, token) { |
(this.consentDialog_) ? this.consentDialog_.show() : Promise.resolve(); |
showConsentDialog.then(function() { |
chrome.identity.getAuthToken({'interactive': true}, |
- that.onAuthComplete_.bind(that, true)); |
+ that.onAuthComplete_.bind( |
+ that, resolve, reject, true)); |
kelvinp
2015/02/18 19:45:24
indentation
John Williams
2015/02/18 20:28:22
Done.
|
}); |
}; |
/** |
- * Internal representation for pair of callWithToken callbacks. |
- * |
- * @param {function(string):void} onOk |
- * @param {function(remoting.Error):void} onError |
- * @constructor |
- * @private |
- */ |
-remoting.Identity.Callbacks = function(onOk, onError) { |
- /** @type {function(string):void} */ |
- this.onOk = onOk; |
- /** @type {function(remoting.Error):void} */ |
- this.onError = onError; |
-}; |
- |
-/** |
* Returns whether the web app has authenticated with the Google services. |
* |
* @return {boolean} |