blob: 1c1131b960bc31f6b26b6957865e5b9f335fb738 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import '@chopsui/prpc-client/prpc-client.js';
/**
* @fileoverview pRPC-related helper functions.
*/
export default class AutoRefreshPrpcClient {
constructor(token, tokenExpiresSec) {
this.token = token;
this.tokenExpiresSec = tokenExpiresSec;
this.prpcClient = new window.chops.rpc.PrpcClient({
insecure: Boolean(location.hostname === 'localhost'),
fetchImpl: (url, options) => {
options.credentials = 'same-origin';
return fetch(url, options);
},
});
}
/**
* Refresh the XSRF token if necessary.
* TODO(ehmaldonado): Figure out how to handle failures to refresh tokens.
* Maybe fire an event that a root page handler could use to show a message.
* @async
*/
async ensureTokenIsValid() {
if (AutoRefreshPrpcClient.isTokenExpired(this.tokenExpiresSec)) {
const headers = {'X-Xsrf-Token': this.token};
const message = {
token: this.token,
tokenPath: 'xhr',
};
const freshToken = await this.prpcClient.call(
'monorail.Sitewide', 'RefreshToken', message, headers);
this.token = freshToken.token;
this.tokenExpiresSec = freshToken.tokenExpiresSec;
}
}
/**
* Sends a pRPC request. Adds this.token to the request message after making
* sure it is fresh.
* @param {string} service Full service name, including package name.
* @param {string} method Service method name.
* @param {Object} message The protobuf message to send.
* @return {Object} The pRPC API response.
*/
call(service, method, message) {
return this.ensureTokenIsValid().then(() => {
const headers = {'X-Xsrf-Token': this.token};
return this.prpcClient.call(service, method, message, headers);
});
}
/**
* Check if the token is expired.
* @param {number} tokenExpiresSec: the expiration time of the token.
* @return {boolean} Whether the token is expired.
*/
static isTokenExpired(tokenExpiresSec) {
const tokenExpiresDate = new Date(tokenExpiresSec * 1000);
return tokenExpiresDate < new Date();
}
}