blob: f7b0575bbdd03ed90fb3d58a87f8130934b92297 [file] [log] [blame]
<!--
Copyright 2016 The LUCI Authors. All rights reserved.
Use of this source code is governed under the Apache License, Version 2.0
that can be found in the LICENSE file.
-->
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/google-signin/google-signin-aware.html">
<link rel="import" href="rpc-code.html">
<link rel="import" href="rpc-error.html">
<link rel="import" href="rpc-call.html">
<!--
The `rpc-client` element can send a RPC request.
Supports pRPC.
Protocol: https://godoc.org/go.chromium.org/luci/common/prpc#hdr-Protocol
-->
<dom-module id="rpc-client">
<template>
<google-signin-aware
id="aware"
on-google-signin-aware-success="_onSignin"
on-google-signin-aware-signed-out="_onSignout"></google-signin-aware>
</template>
<script>
'use strict';
Polymer({
is: 'rpc-client',
properties: {
/**
* If true, use HTTP instead of HTTPS.
* If null or undefined (default), determined automatically:
* - If host equals current host and current protocol is http, then
* false.
* - otherwise true.
*/
insecure: {
type: Boolean,
value: null
},
/**
* pRPC server host, defaults to current document host.
*/
host: {
type: String,
value: document.location.host,
},
/**
* Full service name, including package name.
*/
service: String,
/**
* Service method name.
*/
method: String,
/**
* Request object.
*/
request: {
type: Object,
value: function() {
return {};
}
},
/**
* Request timeout in milliseconds.
*/
timeout: {
type: Number,
value: 0,
},
/**
* OAuth 2.0 access token to use in RPC.
*/
accessToken: {
type: String,
value: null
},
/**
* If true, automatically update "accessToken" with the current access
* token when the sign-in singleton's authentication state changes.
*/
autoToken: {
type: Boolean,
value: false,
},
/**
* If true, automatically sends a request when host, service, method,
* request or accessToken changes.
*/
auto: {
type: Boolean,
value: false
},
/**
* If true, error messages will automatically be logged to the console.
*/
verbose: {
type: Boolean,
value: false
},
/**
* The most recent call made by this client.
*/
lastCall: {
type: Object,
notify: true,
readOnly: true
},
/**
* True while lastCall is in flight.
*/
loading: {
type: Boolean,
notify: true,
readOnly: true,
value: false
},
/**
* lastCall's response.
*
* Note that lastResponse, lastCode and lastError are set when
* lastCall finishes, so if loading is true, they will correspond to the
* result of the previous request.
*/
lastResponse: {
type: Object,
notify: true,
readOnly: true
},
/**
* lastCall's response code.
*/
lastCode: {
type: Number,
notify: true,
readOnly: true
},
/**
* lastCall's error, if any.
* May be an instance of luci.rpc.GrpcError which has response code
* and description.
*/
lastError: {
type: Number,
notify: true,
readOnly: true
},
/**
* Length of time in milliseconds to debounce multiple automatically
* generated requests.
*/
debounceDuration: {
type: Number,
value: 0,
notify: true
}
},
observers: [
('_callOptionsChanged(' +
'host, service, method, request.*, accessToken, auto)')
],
_canCall: function () {
return this.host && this.service && this.method;
},
_callOptionsChanged: function() {
this.debounce('call', function() {
if (this.auto && this._canCall()) {
this.call();
}
}, this.debounceDuration);
},
/**
* Send an RPC request.
* @return {!RpcCallElement}
*/
call: function() {
var call = document.createElement('rpc-call');
call.send({
insecure: this.insecure,
host: this.host,
service: this.service,
method: this.method,
request: this.request,
timeout: this.timeout,
accessToken: this.accessToken
});
this._setLastCall(call);
call.completes.then(
this._onResponse.bind(this)
).catch(
this._onError.bind(this, call)
);
this._setLoading(true);
this.fire('request', {call: call}, {bubbles: false});
return call;
},
_onError: function(call, error) {
this._onCallComplete(call);
if (this.verbose) {
console.error(error);
}
this.fire('error', {
call: call,
error: error
}, {bubbles: false});
},
_onResponse: function(call) {
this._onCallComplete(call);
this.fire('response', {call: call}, {bubbles: false});
},
_onCallComplete: function(call) {
if (call === this.lastCall) {
this._setLastError(call.error);
this._setLastResponse(call.response);
this._setLastCode(call.code);
this._setLoading(false);
}
},
_onSignin: function(e) {
if (this.autoToken) {
this.accessToken = e.detail.access_token;
}
},
_onSignout: function(e) {
if (this.autoToken) {
this.accessToken = null;
}
},
});
</script>
</dom-module>