| Index: tools/telemetry/third_party/gsutilz/third_party/protorpc/experimental/javascript/protorpc.js
|
| diff --git a/tools/telemetry/third_party/gsutilz/third_party/protorpc/experimental/javascript/protorpc.js b/tools/telemetry/third_party/gsutilz/third_party/protorpc/experimental/javascript/protorpc.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..476e530857fd62353db4824c617ca343da845045
|
| --- /dev/null
|
| +++ b/tools/telemetry/third_party/gsutilz/third_party/protorpc/experimental/javascript/protorpc.js
|
| @@ -0,0 +1,371 @@
|
| +// Copyright 2011 Google Inc.
|
| +//
|
| +// Licensed under the Apache License, Version 2.0 (the "License");
|
| +// you may not use this file except in compliance with the License.
|
| +// You may obtain a copy of the License at
|
| +//
|
| +// http://www.apache.org/licenses/LICENSE-2.0
|
| +//
|
| +// Unless required by applicable law or agreed to in writing, software
|
| +// distributed under the License is distributed on an "AS IS" BASIS,
|
| +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| +// See the License for the specific language governing permissions and
|
| +// limitations under the License.
|
| +
|
| +/**
|
| + * @fileoverview Javascript client implementation for ProtoRpc services.
|
| + * @author joetyson@gmail.com (Joe Tyson)
|
| + */
|
| +
|
| +goog.provide('ProtoRpc.RPC');
|
| +goog.provide('ProtoRpc.RPC.State');
|
| +goog.provide('ProtoRpc.ServiceStub');
|
| +
|
| +goog.require('ProtoRpc.EnumDescriptor');
|
| +goog.require('ProtoRpc.Message');
|
| +
|
| +goog.require('goog.json');
|
| +goog.require('goog.net.XmlHttp');
|
| +
|
| +
|
| +/**
|
| + * Represents a client side RPC.
|
| + *
|
| + * @export
|
| + * @param {string} service_path Relative URI where service lives.
|
| + * @param {string} method_name Name of method being invoked.
|
| + * @param {Object} request The request.
|
| + * @param {Function} success Function to call when RPC completes.
|
| + * @param {Function=} error Function to call when RPC has an error.
|
| + * @constructor
|
| + */
|
| +ProtoRpc.RPC = function(service_path, method_name, request, success, error) {
|
| + this.successCallback_ = success;
|
| + this.errorCallback_ = error || null;
|
| +
|
| + this.request_ = request;
|
| +
|
| + var xhr = new goog.net.XmlHttp();
|
| +
|
| + /**
|
| + * Try to open an XMLHttpRequest. If an error occurs, it's generally
|
| + * due to a permission issue.
|
| + * @preserveTry
|
| + */
|
| + try {
|
| + xhr.open('POST', service_path + '.' + method_name, true);
|
| + } catch (err) {
|
| + this.setState_(ProtoRpc.RPC.State.REQUEST_ERROR);
|
| + }
|
| +
|
| + xhr.setRequestHeader('Content-Type', ProtoRpc.RPC.CONTENT_TYPE);
|
| +
|
| + /**
|
| + * Send request or catch error.
|
| + * @preserveTry
|
| + */
|
| + try {
|
| + xhr.onreadystatechange = goog.bind(this.onReadyStateChange_, this);
|
| + // TODO: What if serialization fails?
|
| + xhr.send(goog.json.serialize(request));
|
| + } catch (err) {
|
| + this.setState_(ProtoRpc.RPC.State.REQUEST_ERROR);
|
| + }
|
| +
|
| + this.xhr_ = xhr;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Rpc States.
|
| + * @enum {string}
|
| + */
|
| +ProtoRpc.RPC.State = {
|
| + OK: 'OK',
|
| + RUNNING: 'RUNNING',
|
| + REQUEST_ERROR: 'REQUEST_ERROR',
|
| + SERVER_ERROR: 'SERVER_ERROR',
|
| + NETWORK_ERROR: 'NETWORK_ERROR',
|
| + APPLICATION_ERROR: 'APPLICATION_ERROR'
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Content-Type to use when making remote calls.
|
| + * @const
|
| + */
|
| +ProtoRpc.RPC.CONTENT_TYPE = 'application/json;charset=utf-8';
|
| +
|
| +
|
| +/**
|
| + * Reference to an XMLHttpRequest object being used for RPC.
|
| + * @type {XMLHttpRequest}
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.xhr_ = null;
|
| +
|
| +
|
| +/**
|
| + * Functon to call when RPC completes successfully.
|
| + * @type {Function}
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.successCallback_ = null;
|
| +
|
| +
|
| +/**
|
| + * Function to call when an error happens.
|
| + * @type {Function}
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.errorCallback_ = null;
|
| +
|
| +
|
| +/**
|
| + * The Rpc's request message.
|
| + * @type {Object}
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.request_ = null;
|
| +
|
| +
|
| +/**
|
| + * The Rpc's response from the server.
|
| + * @type {Object}
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.response_ = null;
|
| +
|
| +
|
| +/**
|
| + * The current state of the Rpc.
|
| + * @type {ProtoRpc.RPC.State}
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.state_ = ProtoRpc.RPC.State.RUNNING;
|
| +
|
| +
|
| +/**
|
| + * The Rpc's Error Message, if error.
|
| + * @type {string}
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.errorMessage_ = '';
|
| +
|
| +
|
| +/**
|
| + * The Rpc's Error Name, if error.
|
| + * @type {string}
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.errorName_ = '';
|
| +
|
| +
|
| +/**
|
| + * Method invoked when RPC's xhr readyState is changed.
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.onReadyStateChange_ = function() {
|
| + if (this.state_ != ProtoRpc.RPC.State.RUNNING) {
|
| + return;
|
| + }
|
| +
|
| + if (this.xhr_.readyState != goog.net.XmlHttp.ReadyState.COMPLETE) {
|
| + return;
|
| + }
|
| +
|
| + var status = this.xhr_.status;
|
| + var statusText = this.xhr_.statusText;
|
| + var content = this.xhr_.responseText;
|
| +
|
| + if (status >= 400) {
|
| + /**
|
| + * Try to parse RpcStatus from message.
|
| + * @preserveTry
|
| + */
|
| + try {
|
| + var rpcStatus = goog.json.parse(content);
|
| + this.errorName_ = rpcStatus['error_name'] || null;
|
| + this.errorMessage_ = rpcStatus['error_message'] || null;
|
| + // TODO(joe): More robust RpcStatus handling...
|
| + this.setState_(rpcStatus['state']);
|
| + } catch (err) {
|
| + this.errorName_ = 'Unknown Error.';
|
| + this.setState_(ProtoRpc.RPC.State.REQUEST_ERROR);
|
| + }
|
| + return;
|
| + }
|
| +
|
| + // TODO: validation
|
| + // TODO: What if parsing fails?
|
| + this.response_ = goog.json.parse(content);
|
| + this.setState_(ProtoRpc.RPC.State.OK);
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Set the Rpc's state.
|
| + * @param {ProtoRpc.RPC.State} state The Rpc State to set.
|
| + * @private
|
| + */
|
| +ProtoRpc.RPC.prototype.setState_ = function(state) {
|
| + // TODO: Bitmask "allowed" transitions?
|
| + this.state_ = state;
|
| + if (state != ProtoRpc.RPC.State.OK) {
|
| + this.callErrorHandler_();
|
| + return;
|
| + }
|
| + this.callSuccessHandler_();
|
| +};
|
| +
|
| +
|
| +/** @private */
|
| +ProtoRpc.RPC.prototype.callErrorHandler_ = function() {
|
| + // TODO: optional context/this?
|
| + this.errorCallback_(this);
|
| +};
|
| +
|
| +
|
| +/** @private */
|
| +ProtoRpc.RPC.prototype.callSuccessHandler_ = function() {
|
| + // TODO: optional context/this?
|
| + this.successCallback_(this);
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Get the response from a completed RPC.
|
| + * Throws {@code ProtoRpc.RpcError} if an error occured while
|
| + * running the RPC.
|
| + * @return {Object} The response message from RPC.
|
| + * @export
|
| + */
|
| +ProtoRpc.RPC.prototype.getResponse = function() {
|
| + if (this.state_ != ProtoRpc.RPC.State.OK) {
|
| + throw this.getError();
|
| + }
|
| + return this.response_;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Get the error from a failed RPC. This may be any of the appropriate
|
| + * error types which can be associated with an RPC.
|
| + * @export
|
| + * @return {Error} The Error associated with RPC.
|
| + */
|
| +ProtoRpc.RPC.prototype.getError = function() {
|
| + // TODO: if not in error, do something.
|
| + var error = new Error(this.errorName_);
|
| + error.message = this.errorMessage_;
|
| + error.type = this.state_;
|
| + return error;
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Represents a Service Stub for a given service name, path, and set
|
| + * of methods.
|
| + * @param {string} path The path where the service accepts method calls.
|
| + * @param {Array.<ProtoRpc.MethodDescriptor>} methods An array of method
|
| + * descriptors.
|
| + * @constructor
|
| + */
|
| +ProtoRpc.ServiceStub = function(path, methods) {
|
| + this.path_ = path;
|
| + var l = methods.length;
|
| + for (var i = 0; i < l; i++) {
|
| + this.addMethod_(methods[i]);
|
| + }
|
| +};
|
| +
|
| +
|
| +/**
|
| + * Add a method to the service.
|
| + * @param {ProtoRpc.MethodDescriptor} method_descriptor The method descriptor.
|
| + * @private
|
| + */
|
| +ProtoRpc.ServiceStub.prototype.addMethod_ = function(method_descriptor) {
|
| + var method_name = method_descriptor.name;
|
| + this[method_name] = this.makeMethod_(method_name, this.path_);
|
| +};
|
| +
|
| +/**
|
| + * Helper to make methods.
|
| + * @param {string} name Method name.
|
| + * @param {string} path Service path.
|
| + * @return {function({request: Object,
|
| + * success: function(ProtoRpc.RPC),
|
| + * error: function(ProtoRpc.RPC)})}
|
| + * @private
|
| + */
|
| +ProtoRpc.ServiceStub.prototype.makeMethod_ = function(name, path) {
|
| + return function(kwargs) {
|
| + var request = kwargs['request'] || {};
|
| + var success = kwargs['success'];
|
| + var error = kwargs['error'] || null;
|
| +
|
| + if (!goog.isFunction(success)) {
|
| + throw Error('Success callback needs to be a function!');
|
| + }
|
| +
|
| + if (error && !goog.isFunction(error)) {
|
| + throw Error('Error callback needs to be a function!');
|
| + }
|
| +
|
| + return new ProtoRpc.RPC(path, name, request, success, error);
|
| + };
|
| +};
|
| +
|
| +/**
|
| + * Protojson Specific Serializer.
|
| + * @constructor
|
| + */
|
| +ProtoRpc.Serializer = function() {
|
| + // TODO: Have option for using key's as field number vs. field name.
|
| +};
|
| +
|
| +ProtoRpc.Serializer.prototype.serialize = function(message) {
|
| + var descriptor = message.getDescriptor();
|
| + var fields = descriptor['fields'];
|
| +
|
| + var obj = {};
|
| +
|
| + for (var i = 0; i < fields.length; i++) {
|
| + var field = fields[i];
|
| +
|
| + if (message.has(field)) {
|
| + if (field['label'] == 'REPEATED') {
|
| + var arr = [];
|
| + obj[field.toString()] = arr;
|
| +
|
| + var repeatedValues = message.get(field);
|
| + for (var j = 0; j < repeatedValues.length; j++) {
|
| + arr.push(this.serialize_(field, repeatedValues[j]));
|
| + }
|
| + } else {
|
| + obj[field.toString()] = message.get(field);
|
| + }
|
| + } else {
|
| + // Default values
|
| + }
|
| + }
|
| +};
|
| +
|
| +
|
| +/**
|
| + * @param {ProtoRpc.FieldDescriptor} field Field Descriptor of value.
|
| + * @param {*} value Field's unserialized value.
|
| + */
|
| +ProtoRpc.Serializer.prototype.serialize_ = function(field, value) {
|
| + switch (field['variant']) {
|
| + case ProtoRpc.Variant.MESSAGE:
|
| + return this.serializeMessage_(value);
|
| + break;
|
| + case ProtoRpc.Variant.ENUM:
|
| + return this.serializeEnum_(value);
|
| + break;
|
| + default:
|
| + return value;
|
| + }
|
| +};
|
|
|