[tricium plugin] Handle concurrent _configureOAuthLibrary calls
Copied from Nodir's change to buildbucket plugin:
https://chromium-review.googlesource.com/c/infra/gerrit-plugins/buildbucket/+/1347295
Change-Id: Ic92c7b8e4dda61e0aec747a87c42405a51011d38
Reviewed-on: https://chromium-review.googlesource.com/c/1347413
Reviewed-by: Nodir Turakulov <nodir@chromium.org>
diff --git a/src/main/resources/static/tricium-client.js b/src/main/resources/static/tricium-client.js
index b20c5c2..c926db7 100644
--- a/src/main/resources/static/tricium-client.js
+++ b/src/main/resources/static/tricium-client.js
@@ -26,6 +26,7 @@
_sharedAuthState: {
type: Object,
value: {
+ loading: false,
config: null,
token: null,
},
@@ -238,35 +239,40 @@
* @return {Promise} Resolves upon completion.
*/
async _configureOAuthLibrary() {
- const loggedIn = await this.plugin.restApi().getLoggedIn();
- // No need to configure OAuth if no user is logged in, or if it's
- // already configured.
- if (!loggedIn || this._sharedAuthState.config) {
+ // No need to configure OAuth if it's already configured,
+ // or if it's already being configured.
+ if (this._sharedAuthState.config || this._sharedAuthState.loading) {
return;
}
+ this._sharedAuthState.loading = true;
const gapi = window.gapi;
- await new Promise((resolve) => {
- // gapi library shares state between clients, so if this library is
- // already used by another plugin, there may be unexpected results.
- // TODO(qyearsley): Check whether gapi is already configured, and if
- // so log a message and do nothing.
- // More about gapi:
- // https://developers.google.com/api-client-library/javascript/reference/referencedocs
- gapi.load('config_min', resolve);
- });
- const config = await this._getOAuthConfig();
-
- if (config.hasOwnProperty('auth_url') && config.auth_url) {
- gapi.config.update('oauth-flow/authUrl', config.auth_url);
- }
- if (config.hasOwnProperty('proxy_url') && config.proxy_url) {
- gapi.config.update('oauth-flow/proxyUrl', config.proxy_url);
- }
- this._sharedAuthState.config = config;
-
try {
+ // No need to configure if no use is logged in.
+ const loggedIn = await this.plugin.restApi().getLoggedIn();
+ if (!loggedIn) {
+ return;
+ }
+
+ // The gapi library shares state between clients, so if this library
+ // is used by another plugin, there may be unexpected results;
+ // thus log a warning so that we can easily check if this happens.
+ if (gapi.config && gapi.config.get()) {
+ console.warn('gapi config loaded twice, gapi.config.get() =>',
+ gapi.config.get());
+ }
+ await new Promise((resolve) => { gapi.load('config_min', resolve); });
+ const config = await this._getOAuthConfig();
+
+ if (config.hasOwnProperty('auth_url') && config.auth_url) {
+ gapi.config.update('oauth-flow/authUrl', config.auth_url);
+ }
+ if (config.hasOwnProperty('proxy_url') && config.proxy_url) {
+ gapi.config.update('oauth-flow/proxyUrl', config.proxy_url);
+ }
+ this._sharedAuthState.config = config;
+
await new Promise((resolve) => {
// Loading auth has a side-effect. The URLs should be set before
// loading it.
@@ -274,6 +280,9 @@
});
} catch (err) {
this._sharedAuthState.config = null;
+ console.warn('Failed to configure oauth:', err);
+ } finally {
+ this._sharedAuthState.loading = false;
}
},