Index: server/static/rpcexplorer/rpc-method.html |
diff --git a/server/static/rpcexplorer/rpc-method.html b/server/static/rpcexplorer/rpc-method.html |
new file mode 100644 |
index 0000000000000000000000000000000000000000..c53fde817aa11c82715d85921aee1319e5dcc54f |
--- /dev/null |
+++ b/server/static/rpcexplorer/rpc-method.html |
@@ -0,0 +1,206 @@ |
+<!-- |
+ Copyright 2016 The Chromium Authors. All rights reserved. |
+ Use of this source code is governed by a BSD-style license that can be |
+ found in the LICENSE file. |
+ --> |
+ |
+<link rel="import" href="../bower_components/polymer/polymer.html"> |
+ |
+<link rel="import" href="/static/common/rpc/rpc-client.html"> |
+ |
+<link rel="import" href="rpc-descriptor-util.html"> |
+<link rel="import" href="rpc-editor.html"> |
+ |
+<!-- The `rpc-method` is a service method page --> |
+<dom-module id="rpc-method"> |
+ <template> |
+ <style> |
+ rpc-editor { |
+ height: 300px; |
+ } |
+ button { |
+ margin: 5px; |
+ } |
+ </style> |
+ |
+ <div on-keypress="_onKeypress"> |
+ <rpc-client |
+ id="client" |
+ service="[[service]]" |
+ method="[[method]]" |
+ request="[[requestObject]]" |
+ on-response="_onCallComplete" |
+ on-error="_onCallComplete"> |
+ </rpc-client> |
+ <div>[[methodDesc.source_code_info.leading_comments]]</div> |
+ <hr> |
+ |
+ <p>Request:</p> |
+ <div class="row"> |
+ <div class="col-md-7"> |
+ <rpc-editor value="{{requestText}}" |
+ description="[[description]]" |
+ root-type-name="[[requestTypeName]]"></rpc-editor> |
+ </div> |
+ <div class="col-md-3"> |
+ <p>Ctrl+Space for Autocomplete</p> |
+ <p>Shift+Enter for Send</p> |
+ </div> |
+ </div> |
+ |
+ <div> |
+ <button on-tap="send">Send</button> |
+ </div> |
+ |
+ <div class="alert alert-danger" role="alert" hidden="[[!error]]"> |
+ <template is="dom-if" if="[[error.isGrpcError]]"> |
+ <div> |
+ Code: [[error.code]] |
+ <template is="dom-if" if="[[error.codeName]]"> |
+ ([[error.codeName]]) |
+ </template> |
+ </div> |
+ <div>Description: [[error.description]]</div> |
+ </template> |
+ |
+ <template is="dom-if" if="[[!error.isGrpcError]]"> |
+ [[error]] |
+ </template> |
+ </div> |
+ |
+ <div class="row"> |
+ <div class="col-md-7"> |
+ <rpc-editor value="[[responseText]]"></rpc-editor> |
+ </div> |
+ </div> |
+ </div> |
+ </template> |
+ |
+ <script> |
+ 'use strict'; |
+ |
+ Polymer({ |
+ is: 'rpc-method', |
+ |
+ properties: { |
+ /** @type {FileDescriptorSet} */ |
+ description: Object, |
+ |
+ service: String, |
+ |
+ method: String, |
+ |
+ /** @type {MethodDescriptorProto} */ |
+ methodDesc: { |
+ type: Object, |
+ computed: '_resolveMethod(description, service, method)' |
+ }, |
+ |
+ requestTypeName: { |
+ type: String, |
+ computed: '_getRequestTypeName(methodDesc)' |
+ }, |
+ |
+ /** "request" query string parameter. */ |
+ request: { |
+ type: String, |
+ value: '{}', |
+ observer: '_onRequestChanged', |
+ notify: true |
+ }, |
+ |
+ /** Request editor text. */ |
+ requestText: String, |
+ |
+ /** Parsed from requestText. */ |
+ requestObject: Object, |
+ |
+ /** Response editor text. */ |
+ responseText: String, |
+ |
+ error: { |
+ type: Object, |
+ value: null |
+ } |
+ }, |
+ |
+ _resolveMethod: function(desc, service, method) { |
+ if (!desc || !service || !method) { |
+ return null; |
+ } |
+ var methodDesc = rpcExplorer.descUtil.resolve( |
+ desc, service + '.' + method); |
+ return methodDesc && methodDesc.type === 'method' && methodDesc.desc; |
+ }, |
+ |
+ _getRequestTypeName: function(methodDesc) { |
+ return (methodDesc && |
+ rpcExplorer.descUtil.trimPrefixDot(methodDesc.input_type)); |
+ }, |
+ |
+ _onRequestChanged: function() { |
+ try { |
+ this.requestObject = JSON.parse(this.request); |
+ } catch (e) { |
+ console.error('Invalid request: ' + this.request); |
+ this.requestText = this.request; |
+ return; |
+ } |
+ |
+ // Reformat the request read from query string parameter |
+ // because it gets corrupted there. |
+ this.requestText = JSON.stringify(this.requestObject, null, 4); |
+ }, |
+ |
+ _onKeypress: function(e) { |
+ if (e.key === 'Enter' && e.shiftKey) { |
+ this.send(); |
+ e.preventDefault(); |
+ } |
+ }, |
+ |
+ send: function() { |
+ this.error = null; |
+ try { |
+ this.requestObject = JSON.parse(this.requestText); |
+ |
+ // Reformat request |
+ this.requestText = JSON.stringify(this.requestObject, null, 4); |
+ |
+ // Update URL without a refresh. |
+ history.replaceState( |
+ history.state, document.title, "?request=" + this.requestText); |
+ |
+ // Actually send the request. |
+ this.$.client.call(); |
+ } catch (e) { |
+ this.error = e; |
+ console.error(this.error) |
+ } |
+ }, |
+ |
+ _onCallComplete: function() { |
+ var client = this.$.client; |
+ if (client.lastError) { |
+ console.error(client.lastError); |
+ } |
+ |
+ if (client.lastResponse) { |
+ this.responseText = JSON.stringify(client.lastResponse, null, 4); |
+ } else { |
+ this.responseText = ''; |
+ } |
+ |
+ this.error = client.lastError; |
+ if (this.error instanceof luci.rpc.GrpcError) { |
+ this.error = { |
+ isGrpcError: true, |
+ code: this.error.code, |
+ codeName: luci.rpc.CodeName(this.error.code), |
+ description: this.error.description |
+ }; |
+ } |
+ } |
+ }); |
+ </script> |
+</dom-module> |