| OLD | NEW |
| 1 <!DOCTYPE html><html><head><!-- | 1 <!DOCTYPE html><html><head><!-- |
| 2 @license | 2 @license |
| 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. | 3 Copyright (c) 2016 The Polymer Project Authors. All rights reserved. |
| 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt | 4 This code may only be used under the BSD style license found at http://polymer.g
ithub.io/LICENSE.txt |
| 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt | 5 The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt |
| 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt | 6 The complete set of contributors may be found at http://polymer.github.io/CONTRI
BUTORS.txt |
| 7 Code distributed by Google as part of the polymer project is also | 7 Code distributed by Google as part of the polymer project is also |
| 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt | 8 subject to an additional IP rights grant found at http://polymer.github.io/PATEN
TS.txt |
| 9 --><!-- | 9 --><!-- |
| 10 @license | 10 @license |
| (...skipping 8076 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8087 | 8087 |
| 8088 | 8088 |
| 8089 | 8089 |
| 8090 | 8090 |
| 8091 | 8091 |
| 8092 | 8092 |
| 8093 | 8093 |
| 8094 | 8094 |
| 8095 | 8095 |
| 8096 | 8096 |
| 8097 <script>function MakePromise (asap) { | 8097 <script> |
| 8098 function Promise(fn) { | 8098 window.SwarmingBehaviors = window.SwarmingBehaviors || {}; |
| 8099 » » if (typeof this !== 'object' || typeof fn !== 'function') throw
new TypeError(); | 8099 (function(){ |
| 8100 » » this._state = null; | 8100 // This behavior wraps up all the shared swarming functionality. |
| 8101 » » this._value = null; | 8101 SwarmingBehaviors.CommonBehavior = { |
| 8102 » » this._deferreds = [] | |
| 8103 | 8102 |
| 8104 » » doResolve(fn, resolve.bind(this), reject.bind(this)); | 8103 // _getJsonAsync makes an XHR to a url, parses the response as JSON |
| 8105 » } | 8104 // and sticks the resulting object into the property with the name given |
| 8106 | 8105 // by "bindTo". If busy is defined, the property with that name will be |
| 8107 » function handle(deferred) { | 8106 // set to true while the request is in flight and false afterwards. |
| 8108 » » var me = this; | 8107 // request headers (e.g. authentication) and query params will be used if |
| 8109 » » if (this._state === null) { | 8108 // provided. Query params is an object like {String:Array<String>}. On |
| 8110 » » » this._deferreds.push(deferred); | 8109 // error, bindTo will be set to false. It is not set to undefined |
| 8111 » » » return | 8110 // because computed values in Polymer don't fire if a property is |
| 8112 » » } | 8111 // undefined. Clients should check that bindTo is not falsey. |
| 8113 » » asap(function() { | 8112 _getJsonAsync: function(bindTo, url, busy, headers, params) { |
| 8114 » » » var cb = me._state ? deferred.onFulfilled : deferred.onR
ejected | 8113 if (!bindTo || !url) { |
| 8115 » » » if (typeof cb !== 'function') { | 8114 console.log("Need at least a polymer element to bind to and a url"); |
| 8116 » » » » (me._state ? deferred.resolve : deferred.reject)
(me._value); | 8115 return; |
| 8117 » » » » return; | |
| 8118 » » » } | |
| 8119 » » » var ret; | |
| 8120 » » » try { | |
| 8121 » » » » ret = cb(me._value); | |
| 8122 » » » } | |
| 8123 » » » catch (e) { | |
| 8124 » » » » deferred.reject(e); | |
| 8125 » » » » return; | |
| 8126 » » » } | |
| 8127 » » » deferred.resolve(ret); | |
| 8128 » » }) | |
| 8129 » } | |
| 8130 | |
| 8131 » function resolve(newValue) { | |
| 8132 » » try { //Promise Resolution Procedure: https://github.com/promise
s-aplus/promises-spec#the-promise-resolution-procedure | |
| 8133 » » » if (newValue === this) throw new TypeError(); | |
| 8134 » » » if (newValue && (typeof newValue === 'object' || typeof
newValue === 'function')) { | |
| 8135 » » » » var then = newValue.then; | |
| 8136 » » » » if (typeof then === 'function') { | |
| 8137 » » » » » doResolve(then.bind(newValue), resolve.b
ind(this), reject.bind(this)); | |
| 8138 » » » » » return; | |
| 8139 » » » » } | |
| 8140 » » » } | |
| 8141 » » » this._state = true; | |
| 8142 » » » this._value = newValue; | |
| 8143 » » » finale.call(this); | |
| 8144 » » } catch (e) { reject.call(this, e); } | |
| 8145 » } | |
| 8146 | |
| 8147 » function reject(newValue) { | |
| 8148 » » this._state = false; | |
| 8149 » » this._value = newValue; | |
| 8150 » » finale.call(this); | |
| 8151 » } | |
| 8152 | |
| 8153 » function finale() { | |
| 8154 » » for (var i = 0, len = this._deferreds.length; i < len; i++) { | |
| 8155 » » » handle.call(this, this._deferreds[i]); | |
| 8156 » » } | |
| 8157 » » this._deferreds = null; | |
| 8158 » } | |
| 8159 | |
| 8160 » /** | |
| 8161 » * Take a potentially misbehaving resolver function and make sure | |
| 8162 » * onFulfilled and onRejected are only called once. | |
| 8163 » * | |
| 8164 » * Makes no guarantees about asynchrony. | |
| 8165 » */ | |
| 8166 » function doResolve(fn, onFulfilled, onRejected) { | |
| 8167 » » var done = false; | |
| 8168 » » try { | |
| 8169 » » » fn(function (value) { | |
| 8170 » » » » if (done) return; | |
| 8171 » » » » done = true; | |
| 8172 » » » » onFulfilled(value); | |
| 8173 » » » }, function (reason) { | |
| 8174 » » » » if (done) return; | |
| 8175 » » » » done = true; | |
| 8176 » » » » onRejected(reason); | |
| 8177 » » » }) | |
| 8178 » » } catch (ex) { | |
| 8179 » » » if (done) return; | |
| 8180 » » » done = true; | |
| 8181 » » » onRejected(ex); | |
| 8182 » » } | |
| 8183 » } | |
| 8184 | |
| 8185 » Promise.prototype['catch'] = function (onRejected) { | |
| 8186 » » return this.then(null, onRejected); | |
| 8187 » }; | |
| 8188 | |
| 8189 » Promise.prototype.then = function(onFulfilled, onRejected) { | |
| 8190 » » var me = this; | |
| 8191 » » return new Promise(function(resolve, reject) { | |
| 8192 handle.call(me, { | |
| 8193 onFulfilled: onFulfilled, | |
| 8194 onRejected: onRejected, | |
| 8195 resolve: resolve, | |
| 8196 reject: reject | |
| 8197 }); | |
| 8198 » » }) | |
| 8199 » }; | |
| 8200 | |
| 8201 » Promise.resolve = function (value) { | |
| 8202 » » if (value && typeof value === 'object' && value.constructor ===
Promise) { | |
| 8203 » » » return value; | |
| 8204 » » } | |
| 8205 | |
| 8206 » » return new Promise(function (resolve) { | |
| 8207 » » » resolve(value); | |
| 8208 » » }); | |
| 8209 » }; | |
| 8210 | |
| 8211 » Promise.reject = function (value) { | |
| 8212 » » return new Promise(function (resolve, reject) { | |
| 8213 » » » reject(value); | |
| 8214 » » }); | |
| 8215 » }; | |
| 8216 | |
| 8217 » | |
| 8218 return Promise; | |
| 8219 } | |
| 8220 | |
| 8221 if (typeof module !== 'undefined') { | |
| 8222 module.exports = MakePromise; | |
| 8223 } | |
| 8224 | |
| 8225 </script> | |
| 8226 <script> | |
| 8227 if (!window.Promise) { | |
| 8228 window.Promise = MakePromise(Polymer.Base.async); | |
| 8229 } | |
| 8230 </script> | |
| 8231 <script> | |
| 8232 'use strict'; | |
| 8233 | |
| 8234 Polymer({ | |
| 8235 is: 'iron-request', | |
| 8236 | |
| 8237 hostAttributes: { | |
| 8238 hidden: true | |
| 8239 }, | |
| 8240 | |
| 8241 properties: { | |
| 8242 | |
| 8243 /** | |
| 8244 * A reference to the XMLHttpRequest instance used to generate the | |
| 8245 * network request. | |
| 8246 * | |
| 8247 * @type {XMLHttpRequest} | |
| 8248 */ | |
| 8249 xhr: { | |
| 8250 type: Object, | |
| 8251 notify: true, | |
| 8252 readOnly: true, | |
| 8253 value: function() { | |
| 8254 return new XMLHttpRequest(); | |
| 8255 } | 8116 } |
| 8117 if (busy) { |
| 8118 this.set(busy, true); |
| 8119 } |
| 8120 url = url + "?" + sk.query.fromParamSet(params); |
| 8121 sk.request("GET", url, "", headers).then(JSON.parse).then(function(json)
{ |
| 8122 this.set(bindTo, json); |
| 8123 if (busy) { |
| 8124 this.set(busy, false); |
| 8125 } |
| 8126 }.bind(this)).catch(function(reason){ |
| 8127 console.log("Reason for failure of request to " + url, reason); |
| 8128 this.set(bindTo, false); |
| 8129 if (busy) { |
| 8130 this.set(busy, false); |
| 8131 } |
| 8132 }.bind(this)); |
| 8256 }, | 8133 }, |
| 8257 | 8134 |
| 8258 /** | 8135 _not: function(a) { |
| 8259 * A reference to the parsed response body, if the `xhr` has completely | 8136 return !a; |
| 8260 * resolved. | |
| 8261 * | |
| 8262 * @type {*} | |
| 8263 * @default null | |
| 8264 */ | |
| 8265 response: { | |
| 8266 type: Object, | |
| 8267 notify: true, | |
| 8268 readOnly: true, | |
| 8269 value: function() { | |
| 8270 return null; | |
| 8271 } | |
| 8272 }, | 8137 }, |
| 8273 | 8138 |
| 8274 /** | 8139 _or: function() { |
| 8275 * A reference to the status code, if the `xhr` has completely resolved. | 8140 var result = false; |
| 8276 */ | 8141 // can't use .foreach, as arguments isn't really an Array. |
| 8277 status: { | 8142 for (var i = 0; i < arguments.length; i++) { |
| 8278 type: Number, | 8143 result = result || arguments[i]; |
| 8279 notify: true, | 8144 } |
| 8280 readOnly: true, | 8145 return result; |
| 8281 value: 0 | |
| 8282 }, | 8146 }, |
| 8283 | 8147 }; |
| 8284 /** | 8148 })(); |
| 8285 * A reference to the status text, if the `xhr` has completely resolved. | |
| 8286 */ | |
| 8287 statusText: { | |
| 8288 type: String, | |
| 8289 notify: true, | |
| 8290 readOnly: true, | |
| 8291 value: '' | |
| 8292 }, | |
| 8293 | |
| 8294 /** | |
| 8295 * A promise that resolves when the `xhr` response comes back, or rejects | |
| 8296 * if there is an error before the `xhr` completes. | |
| 8297 * | |
| 8298 * @type {Promise} | |
| 8299 */ | |
| 8300 completes: { | |
| 8301 type: Object, | |
| 8302 readOnly: true, | |
| 8303 notify: true, | |
| 8304 value: function() { | |
| 8305 return new Promise(function (resolve, reject) { | |
| 8306 this.resolveCompletes = resolve; | |
| 8307 this.rejectCompletes = reject; | |
| 8308 }.bind(this)); | |
| 8309 } | |
| 8310 }, | |
| 8311 | |
| 8312 /** | |
| 8313 * An object that contains progress information emitted by the XHR if | |
| 8314 * available. | |
| 8315 * | |
| 8316 * @default {} | |
| 8317 */ | |
| 8318 progress: { | |
| 8319 type: Object, | |
| 8320 notify: true, | |
| 8321 readOnly: true, | |
| 8322 value: function() { | |
| 8323 return {}; | |
| 8324 } | |
| 8325 }, | |
| 8326 | |
| 8327 /** | |
| 8328 * Aborted will be true if an abort of the request is attempted. | |
| 8329 */ | |
| 8330 aborted: { | |
| 8331 type: Boolean, | |
| 8332 notify: true, | |
| 8333 readOnly: true, | |
| 8334 value: false, | |
| 8335 }, | |
| 8336 | |
| 8337 /** | |
| 8338 * Errored will be true if the browser fired an error event from the | |
| 8339 * XHR object (mainly network errors). | |
| 8340 */ | |
| 8341 errored: { | |
| 8342 type: Boolean, | |
| 8343 notify: true, | |
| 8344 readOnly: true, | |
| 8345 value: false | |
| 8346 }, | |
| 8347 | |
| 8348 /** | |
| 8349 * TimedOut will be true if the XHR threw a timeout event. | |
| 8350 */ | |
| 8351 timedOut: { | |
| 8352 type: Boolean, | |
| 8353 notify: true, | |
| 8354 readOnly: true, | |
| 8355 value: false | |
| 8356 } | |
| 8357 }, | |
| 8358 | |
| 8359 /** | |
| 8360 * Succeeded is true if the request succeeded. The request succeeded if it | |
| 8361 * loaded without error, wasn't aborted, and the status code is ≥ 200, and | |
| 8362 * < 300, or if the status code is 0. | |
| 8363 * | |
| 8364 * The status code 0 is accepted as a success because some schemes - e.g. | |
| 8365 * file:// - don't provide status codes. | |
| 8366 * | |
| 8367 * @return {boolean} | |
| 8368 */ | |
| 8369 get succeeded() { | |
| 8370 if (this.errored || this.aborted || this.timedOut) { | |
| 8371 return false; | |
| 8372 } | |
| 8373 var status = this.xhr.status || 0; | |
| 8374 | |
| 8375 // Note: if we are using the file:// protocol, the status code will be 0 | |
| 8376 // for all outcomes (successful or otherwise). | |
| 8377 return status === 0 || | |
| 8378 (status >= 200 && status < 300); | |
| 8379 }, | |
| 8380 | |
| 8381 /** | |
| 8382 * Sends an HTTP request to the server and returns the XHR object. | |
| 8383 * | |
| 8384 * The handling of the `body` parameter will vary based on the Content-Type | |
| 8385 * header. See the docs for iron-ajax's `body` param for details. | |
| 8386 * | |
| 8387 * @param {{ | |
| 8388 * url: string, | |
| 8389 * method: (string|undefined), | |
| 8390 * async: (boolean|undefined), | |
| 8391 * body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|u
ndefined|Object), | |
| 8392 * headers: (Object|undefined), | |
| 8393 * handleAs: (string|undefined), | |
| 8394 * jsonPrefix: (string|undefined), | |
| 8395 * withCredentials: (boolean|undefined)}} options - | |
| 8396 * url The url to which the request is sent. | |
| 8397 * method The HTTP method to use, default is GET. | |
| 8398 * async By default, all requests are sent asynchronously. To send synch
ronous requests, | |
| 8399 * set to false. | |
| 8400 * body The content for the request body for POST method. | |
| 8401 * headers HTTP request headers. | |
| 8402 * handleAs The response type. Default is 'text'. | |
| 8403 * withCredentials Whether or not to send credentials on the request. De
fault is false. | |
| 8404 * timeout: (Number|undefined) | |
| 8405 * @return {Promise} | |
| 8406 */ | |
| 8407 send: function (options) { | |
| 8408 var xhr = this.xhr; | |
| 8409 | |
| 8410 if (xhr.readyState > 0) { | |
| 8411 return null; | |
| 8412 } | |
| 8413 | |
| 8414 xhr.addEventListener('progress', function (progress) { | |
| 8415 this._setProgress({ | |
| 8416 lengthComputable: progress.lengthComputable, | |
| 8417 loaded: progress.loaded, | |
| 8418 total: progress.total | |
| 8419 }); | |
| 8420 }.bind(this)) | |
| 8421 | |
| 8422 xhr.addEventListener('error', function (error) { | |
| 8423 this._setErrored(true); | |
| 8424 this._updateStatus(); | |
| 8425 this.rejectCompletes(error); | |
| 8426 }.bind(this)); | |
| 8427 | |
| 8428 xhr.addEventListener('timeout', function (error) { | |
| 8429 this._setTimedOut(true); | |
| 8430 this._updateStatus(); | |
| 8431 this.rejectCompletes(error); | |
| 8432 }.bind(this)); | |
| 8433 | |
| 8434 xhr.addEventListener('abort', function () { | |
| 8435 this._updateStatus(); | |
| 8436 this.rejectCompletes(new Error('Request aborted.')); | |
| 8437 }.bind(this)); | |
| 8438 | |
| 8439 // Called after all of the above. | |
| 8440 xhr.addEventListener('loadend', function () { | |
| 8441 this._updateStatus(); | |
| 8442 this._setResponse(this.parseResponse()); | |
| 8443 | |
| 8444 if (!this.succeeded) { | |
| 8445 this.rejectCompletes(new Error('The request failed with status code: '
+ this.xhr.status)); | |
| 8446 return; | |
| 8447 } | |
| 8448 | |
| 8449 this.resolveCompletes(this); | |
| 8450 }.bind(this)); | |
| 8451 | |
| 8452 this.url = options.url; | |
| 8453 xhr.open( | |
| 8454 options.method || 'GET', | |
| 8455 options.url, | |
| 8456 options.async !== false | |
| 8457 ); | |
| 8458 | |
| 8459 var acceptType = { | |
| 8460 'json': 'application/json', | |
| 8461 'text': 'text/plain', | |
| 8462 'html': 'text/html', | |
| 8463 'xml': 'application/xml', | |
| 8464 'arraybuffer': 'application/octet-stream' | |
| 8465 }[options.handleAs]; | |
| 8466 var headers = options.headers || Object.create(null); | |
| 8467 var newHeaders = Object.create(null); | |
| 8468 for (var key in headers) { | |
| 8469 newHeaders[key.toLowerCase()] = headers[key]; | |
| 8470 } | |
| 8471 headers = newHeaders; | |
| 8472 | |
| 8473 if (acceptType && !headers['accept']) { | |
| 8474 headers['accept'] = acceptType; | |
| 8475 } | |
| 8476 Object.keys(headers).forEach(function (requestHeader) { | |
| 8477 if (/[A-Z]/.test(requestHeader)) { | |
| 8478 Polymer.Base._error('Headers must be lower case, got', requestHeader); | |
| 8479 } | |
| 8480 xhr.setRequestHeader( | |
| 8481 requestHeader, | |
| 8482 headers[requestHeader] | |
| 8483 ); | |
| 8484 }, this); | |
| 8485 | |
| 8486 if (options.async !== false) { | |
| 8487 if (options.async) { | |
| 8488 xhr.timeout = options.timeout; | |
| 8489 } | |
| 8490 | |
| 8491 var handleAs = options.handleAs; | |
| 8492 | |
| 8493 // If a JSON prefix is present, the responseType must be 'text' or the | |
| 8494 // browser won’t be able to parse the response. | |
| 8495 if (!!options.jsonPrefix || !handleAs) { | |
| 8496 handleAs = 'text'; | |
| 8497 } | |
| 8498 | |
| 8499 // In IE, `xhr.responseType` is an empty string when the response | |
| 8500 // returns. Hence, caching it as `xhr._responseType`. | |
| 8501 xhr.responseType = xhr._responseType = handleAs; | |
| 8502 | |
| 8503 // Cache the JSON prefix, if it exists. | |
| 8504 if (!!options.jsonPrefix) { | |
| 8505 xhr._jsonPrefix = options.jsonPrefix; | |
| 8506 } | |
| 8507 } | |
| 8508 | |
| 8509 xhr.withCredentials = !!options.withCredentials; | |
| 8510 | |
| 8511 | |
| 8512 var body = this._encodeBodyObject(options.body, headers['content-type']); | |
| 8513 | |
| 8514 xhr.send( | |
| 8515 /** @type {ArrayBuffer|ArrayBufferView|Blob|Document|FormData| | |
| 8516 null|string|undefined} */ | |
| 8517 (body)); | |
| 8518 | |
| 8519 return this.completes; | |
| 8520 }, | |
| 8521 | |
| 8522 /** | |
| 8523 * Attempts to parse the response body of the XHR. If parsing succeeds, | |
| 8524 * the value returned will be deserialized based on the `responseType` | |
| 8525 * set on the XHR. | |
| 8526 * | |
| 8527 * @return {*} The parsed response, | |
| 8528 * or undefined if there was an empty response or parsing failed. | |
| 8529 */ | |
| 8530 parseResponse: function () { | |
| 8531 var xhr = this.xhr; | |
| 8532 var responseType = xhr.responseType || xhr._responseType; | |
| 8533 var preferResponseText = !this.xhr.responseType; | |
| 8534 var prefixLen = (xhr._jsonPrefix && xhr._jsonPrefix.length) || 0; | |
| 8535 | |
| 8536 try { | |
| 8537 switch (responseType) { | |
| 8538 case 'json': | |
| 8539 // If the xhr object doesn't have a natural `xhr.responseType`, | |
| 8540 // we can assume that the browser hasn't parsed the response for us, | |
| 8541 // and so parsing is our responsibility. Likewise if response is | |
| 8542 // undefined, as there's no way to encode undefined in JSON. | |
| 8543 if (preferResponseText || xhr.response === undefined) { | |
| 8544 // Try to emulate the JSON section of the response body section of | |
| 8545 // the spec: https://xhr.spec.whatwg.org/#response-body | |
| 8546 // That is to say, we try to parse as JSON, but if anything goes | |
| 8547 // wrong return null. | |
| 8548 try { | |
| 8549 return JSON.parse(xhr.responseText); | |
| 8550 } catch (_) { | |
| 8551 return null; | |
| 8552 } | |
| 8553 } | |
| 8554 | |
| 8555 return xhr.response; | |
| 8556 case 'xml': | |
| 8557 return xhr.responseXML; | |
| 8558 case 'blob': | |
| 8559 case 'document': | |
| 8560 case 'arraybuffer': | |
| 8561 return xhr.response; | |
| 8562 case 'text': | |
| 8563 default: { | |
| 8564 // If `prefixLen` is set, it implies the response should be parsed | |
| 8565 // as JSON once the prefix of length `prefixLen` is stripped from | |
| 8566 // it. Emulate the behavior above where null is returned on failure | |
| 8567 // to parse. | |
| 8568 if (prefixLen) { | |
| 8569 try { | |
| 8570 return JSON.parse(xhr.responseText.substring(prefixLen)); | |
| 8571 } catch (_) { | |
| 8572 return null; | |
| 8573 } | |
| 8574 } | |
| 8575 return xhr.responseText; | |
| 8576 } | |
| 8577 } | |
| 8578 } catch (e) { | |
| 8579 this.rejectCompletes(new Error('Could not parse response. ' + e.message)
); | |
| 8580 } | |
| 8581 }, | |
| 8582 | |
| 8583 /** | |
| 8584 * Aborts the request. | |
| 8585 */ | |
| 8586 abort: function () { | |
| 8587 this._setAborted(true); | |
| 8588 this.xhr.abort(); | |
| 8589 }, | |
| 8590 | |
| 8591 /** | |
| 8592 * @param {*} body The given body of the request to try and encode. | |
| 8593 * @param {?string} contentType The given content type, to infer an encoding | |
| 8594 * from. | |
| 8595 * @return {*} Either the encoded body as a string, if successful, | |
| 8596 * or the unaltered body object if no encoding could be inferred. | |
| 8597 */ | |
| 8598 _encodeBodyObject: function(body, contentType) { | |
| 8599 if (typeof body == 'string') { | |
| 8600 return body; // Already encoded. | |
| 8601 } | |
| 8602 var bodyObj = /** @type {Object} */ (body); | |
| 8603 switch(contentType) { | |
| 8604 case('application/json'): | |
| 8605 return JSON.stringify(bodyObj); | |
| 8606 case('application/x-www-form-urlencoded'): | |
| 8607 return this._wwwFormUrlEncode(bodyObj); | |
| 8608 } | |
| 8609 return body; | |
| 8610 }, | |
| 8611 | |
| 8612 /** | |
| 8613 * @param {Object} object The object to encode as x-www-form-urlencoded. | |
| 8614 * @return {string} . | |
| 8615 */ | |
| 8616 _wwwFormUrlEncode: function(object) { | |
| 8617 if (!object) { | |
| 8618 return ''; | |
| 8619 } | |
| 8620 var pieces = []; | |
| 8621 Object.keys(object).forEach(function(key) { | |
| 8622 // TODO(rictic): handle array values here, in a consistent way with | |
| 8623 // iron-ajax params. | |
| 8624 pieces.push( | |
| 8625 this._wwwFormUrlEncodePiece(key) + '=' + | |
| 8626 this._wwwFormUrlEncodePiece(object[key])); | |
| 8627 }, this); | |
| 8628 return pieces.join('&'); | |
| 8629 }, | |
| 8630 | |
| 8631 /** | |
| 8632 * @param {*} str A key or value to encode as x-www-form-urlencoded. | |
| 8633 * @return {string} . | |
| 8634 */ | |
| 8635 _wwwFormUrlEncodePiece: function(str) { | |
| 8636 // Spec says to normalize newlines to \r\n and replace %20 spaces with +. | |
| 8637 // jQuery does this as well, so this is likely to be widely compatible. | |
| 8638 if (str === null) { | |
| 8639 return ''; | |
| 8640 } | |
| 8641 return encodeURIComponent(str.toString().replace(/\r?\n/g, '\r\n')) | |
| 8642 .replace(/%20/g, '+'); | |
| 8643 }, | |
| 8644 | |
| 8645 /** | |
| 8646 * Updates the status code and status text. | |
| 8647 */ | |
| 8648 _updateStatus: function() { | |
| 8649 this._setStatus(this.xhr.status); | |
| 8650 this._setStatusText((this.xhr.statusText === undefined) ? '' : this.xhr.st
atusText); | |
| 8651 } | |
| 8652 }); | |
| 8653 </script> | 8149 </script> |
| 8654 | |
| 8655 <script> | |
| 8656 'use strict'; | |
| 8657 | |
| 8658 Polymer({ | |
| 8659 | |
| 8660 is: 'iron-ajax', | |
| 8661 | |
| 8662 /** | |
| 8663 * Fired when a request is sent. | |
| 8664 * | |
| 8665 * @event request | |
| 8666 * @event iron-ajax-request | |
| 8667 */ | |
| 8668 | |
| 8669 /** | |
| 8670 * Fired when a response is received. | |
| 8671 * | |
| 8672 * @event response | |
| 8673 * @event iron-ajax-response | |
| 8674 */ | |
| 8675 | |
| 8676 /** | |
| 8677 * Fired when an error is received. | |
| 8678 * | |
| 8679 * @event error | |
| 8680 * @event iron-ajax-error | |
| 8681 */ | |
| 8682 | |
| 8683 hostAttributes: { | |
| 8684 hidden: true | |
| 8685 }, | |
| 8686 | |
| 8687 properties: { | |
| 8688 /** | |
| 8689 * The URL target of the request. | |
| 8690 */ | |
| 8691 url: { | |
| 8692 type: String | |
| 8693 }, | |
| 8694 | |
| 8695 /** | |
| 8696 * An object that contains query parameters to be appended to the | |
| 8697 * specified `url` when generating a request. If you wish to set the body | |
| 8698 * content when making a POST request, you should use the `body` property | |
| 8699 * instead. | |
| 8700 */ | |
| 8701 params: { | |
| 8702 type: Object, | |
| 8703 value: function() { | |
| 8704 return {}; | |
| 8705 } | |
| 8706 }, | |
| 8707 | |
| 8708 /** | |
| 8709 * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'. | |
| 8710 * Default is 'GET'. | |
| 8711 */ | |
| 8712 method: { | |
| 8713 type: String, | |
| 8714 value: 'GET' | |
| 8715 }, | |
| 8716 | |
| 8717 /** | |
| 8718 * HTTP request headers to send. | |
| 8719 * | |
| 8720 * Example: | |
| 8721 * | |
| 8722 * <iron-ajax | |
| 8723 * auto | |
| 8724 * url="http://somesite.com" | |
| 8725 * headers='{"X-Requested-With": "XMLHttpRequest"}' | |
| 8726 * handle-as="json"></iron-ajax> | |
| 8727 * | |
| 8728 * Note: setting a `Content-Type` header here will override the value | |
| 8729 * specified by the `contentType` property of this element. | |
| 8730 */ | |
| 8731 headers: { | |
| 8732 type: Object, | |
| 8733 value: function() { | |
| 8734 return {}; | |
| 8735 } | |
| 8736 }, | |
| 8737 | |
| 8738 /** | |
| 8739 * Content type to use when sending data. If the `contentType` property | |
| 8740 * is set and a `Content-Type` header is specified in the `headers` | |
| 8741 * property, the `headers` property value will take precedence. | |
| 8742 * | |
| 8743 * Varies the handling of the `body` param. | |
| 8744 */ | |
| 8745 contentType: { | |
| 8746 type: String, | |
| 8747 value: null | |
| 8748 }, | |
| 8749 | |
| 8750 /** | |
| 8751 * Body content to send with the request, typically used with "POST" | |
| 8752 * requests. | |
| 8753 * | |
| 8754 * If body is a string it will be sent unmodified. | |
| 8755 * | |
| 8756 * If Content-Type is set to a value listed below, then | |
| 8757 * the body will be encoded accordingly. | |
| 8758 * | |
| 8759 * * `content-type="application/json"` | |
| 8760 * * body is encoded like `{"foo":"bar baz","x":1}` | |
| 8761 * * `content-type="application/x-www-form-urlencoded"` | |
| 8762 * * body is encoded like `foo=bar+baz&x=1` | |
| 8763 * | |
| 8764 * Otherwise the body will be passed to the browser unmodified, and it | |
| 8765 * will handle any encoding (e.g. for FormData, Blob, ArrayBuffer). | |
| 8766 * | |
| 8767 * @type (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|u
ndefined|Object) | |
| 8768 */ | |
| 8769 body: { | |
| 8770 type: Object, | |
| 8771 value: null | |
| 8772 }, | |
| 8773 | |
| 8774 /** | |
| 8775 * Toggle whether XHR is synchronous or asynchronous. Don't change this | |
| 8776 * to true unless You Know What You Are Doingâ„¢. | |
| 8777 */ | |
| 8778 sync: { | |
| 8779 type: Boolean, | |
| 8780 value: false | |
| 8781 }, | |
| 8782 | |
| 8783 /** | |
| 8784 * Specifies what data to store in the `response` property, and | |
| 8785 * to deliver as `event.detail.response` in `response` events. | |
| 8786 * | |
| 8787 * One of: | |
| 8788 * | |
| 8789 * `text`: uses `XHR.responseText`. | |
| 8790 * | |
| 8791 * `xml`: uses `XHR.responseXML`. | |
| 8792 * | |
| 8793 * `json`: uses `XHR.responseText` parsed as JSON. | |
| 8794 * | |
| 8795 * `arraybuffer`: uses `XHR.response`. | |
| 8796 * | |
| 8797 * `blob`: uses `XHR.response`. | |
| 8798 * | |
| 8799 * `document`: uses `XHR.response`. | |
| 8800 */ | |
| 8801 handleAs: { | |
| 8802 type: String, | |
| 8803 value: 'json' | |
| 8804 }, | |
| 8805 | |
| 8806 /** | |
| 8807 * Set the withCredentials flag on the request. | |
| 8808 */ | |
| 8809 withCredentials: { | |
| 8810 type: Boolean, | |
| 8811 value: false | |
| 8812 }, | |
| 8813 | |
| 8814 /** | |
| 8815 * Set the timeout flag on the request. | |
| 8816 */ | |
| 8817 timeout: { | |
| 8818 type: Number, | |
| 8819 value: 0 | |
| 8820 }, | |
| 8821 | |
| 8822 /** | |
| 8823 * If true, automatically performs an Ajax request when either `url` or | |
| 8824 * `params` changes. | |
| 8825 */ | |
| 8826 auto: { | |
| 8827 type: Boolean, | |
| 8828 value: false | |
| 8829 }, | |
| 8830 | |
| 8831 /** | |
| 8832 * If true, error messages will automatically be logged to the console. | |
| 8833 */ | |
| 8834 verbose: { | |
| 8835 type: Boolean, | |
| 8836 value: false | |
| 8837 }, | |
| 8838 | |
| 8839 /** | |
| 8840 * The most recent request made by this iron-ajax element. | |
| 8841 */ | |
| 8842 lastRequest: { | |
| 8843 type: Object, | |
| 8844 notify: true, | |
| 8845 readOnly: true | |
| 8846 }, | |
| 8847 | |
| 8848 /** | |
| 8849 * True while lastRequest is in flight. | |
| 8850 */ | |
| 8851 loading: { | |
| 8852 type: Boolean, | |
| 8853 notify: true, | |
| 8854 readOnly: true | |
| 8855 }, | |
| 8856 | |
| 8857 /** | |
| 8858 * lastRequest's response. | |
| 8859 * | |
| 8860 * Note that lastResponse and lastError are set when lastRequest finishes, | |
| 8861 * so if loading is true, then lastResponse and lastError will correspond | |
| 8862 * to the result of the previous request. | |
| 8863 * | |
| 8864 * The type of the response is determined by the value of `handleAs` at | |
| 8865 * the time that the request was generated. | |
| 8866 * | |
| 8867 * @type {Object} | |
| 8868 */ | |
| 8869 lastResponse: { | |
| 8870 type: Object, | |
| 8871 notify: true, | |
| 8872 readOnly: true | |
| 8873 }, | |
| 8874 | |
| 8875 /** | |
| 8876 * lastRequest's error, if any. | |
| 8877 * | |
| 8878 * @type {Object} | |
| 8879 */ | |
| 8880 lastError: { | |
| 8881 type: Object, | |
| 8882 notify: true, | |
| 8883 readOnly: true | |
| 8884 }, | |
| 8885 | |
| 8886 /** | |
| 8887 * An Array of all in-flight requests originating from this iron-ajax | |
| 8888 * element. | |
| 8889 */ | |
| 8890 activeRequests: { | |
| 8891 type: Array, | |
| 8892 notify: true, | |
| 8893 readOnly: true, | |
| 8894 value: function() { | |
| 8895 return []; | |
| 8896 } | |
| 8897 }, | |
| 8898 | |
| 8899 /** | |
| 8900 * Length of time in milliseconds to debounce multiple automatically gener
ated requests. | |
| 8901 */ | |
| 8902 debounceDuration: { | |
| 8903 type: Number, | |
| 8904 value: 0, | |
| 8905 notify: true | |
| 8906 }, | |
| 8907 | |
| 8908 /** | |
| 8909 * Prefix to be stripped from a JSON response before parsing it. | |
| 8910 * | |
| 8911 * In order to prevent an attack using CSRF with Array responses | |
| 8912 * (http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnera
bility.aspx/) | |
| 8913 * many backends will mitigate this by prefixing all JSON response bodies | |
| 8914 * with a string that would be nonsensical to a JavaScript parser. | |
| 8915 * | |
| 8916 */ | |
| 8917 jsonPrefix: { | |
| 8918 type: String, | |
| 8919 value: '' | |
| 8920 }, | |
| 8921 | |
| 8922 /** | |
| 8923 * By default, iron-ajax's events do not bubble. Setting this attribute wi
ll cause its | |
| 8924 * request and response events as well as its iron-ajax-request, -response
, and -error | |
| 8925 * events to bubble to the window object. The vanilla error event never bu
bbles when | |
| 8926 * using shadow dom even if this.bubbles is true because a scoped flag is
not passed with | |
| 8927 * it (first link) and because the shadow dom spec did not used to allow c
ertain events, | |
| 8928 * including events named error, to leak outside of shadow trees (second l
ink). | |
| 8929 * https://www.w3.org/TR/shadow-dom/#scoped-flag | |
| 8930 * https://www.w3.org/TR/2015/WD-shadow-dom-20151215/#events-that-are-not-
leaked-into-ancestor-trees | |
| 8931 */ | |
| 8932 bubbles: { | |
| 8933 type: Boolean, | |
| 8934 value: false | |
| 8935 }, | |
| 8936 | |
| 8937 _boundHandleResponse: { | |
| 8938 type: Function, | |
| 8939 value: function() { | |
| 8940 return this._handleResponse.bind(this); | |
| 8941 } | |
| 8942 } | |
| 8943 }, | |
| 8944 | |
| 8945 observers: [ | |
| 8946 '_requestOptionsChanged(url, method, params.*, headers, contentType, ' + | |
| 8947 'body, sync, handleAs, jsonPrefix, withCredentials, timeout, auto)' | |
| 8948 ], | |
| 8949 | |
| 8950 /** | |
| 8951 * The query string that should be appended to the `url`, serialized from | |
| 8952 * the current value of `params`. | |
| 8953 * | |
| 8954 * @return {string} | |
| 8955 */ | |
| 8956 get queryString () { | |
| 8957 var queryParts = []; | |
| 8958 var param; | |
| 8959 var value; | |
| 8960 | |
| 8961 for (param in this.params) { | |
| 8962 value = this.params[param]; | |
| 8963 param = window.encodeURIComponent(param); | |
| 8964 | |
| 8965 if (Array.isArray(value)) { | |
| 8966 for (var i = 0; i < value.length; i++) { | |
| 8967 queryParts.push(param + '=' + window.encodeURIComponent(value[i])); | |
| 8968 } | |
| 8969 } else if (value !== null) { | |
| 8970 queryParts.push(param + '=' + window.encodeURIComponent(value)); | |
| 8971 } else { | |
| 8972 queryParts.push(param); | |
| 8973 } | |
| 8974 } | |
| 8975 | |
| 8976 return queryParts.join('&'); | |
| 8977 }, | |
| 8978 | |
| 8979 /** | |
| 8980 * The `url` with query string (if `params` are specified), suitable for | |
| 8981 * providing to an `iron-request` instance. | |
| 8982 * | |
| 8983 * @return {string} | |
| 8984 */ | |
| 8985 get requestUrl() { | |
| 8986 var queryString = this.queryString; | |
| 8987 var url = this.url || ''; | |
| 8988 | |
| 8989 if (queryString) { | |
| 8990 var bindingChar = url.indexOf('?') >= 0 ? '&' : '?'; | |
| 8991 return url + bindingChar + queryString; | |
| 8992 } | |
| 8993 | |
| 8994 return url; | |
| 8995 }, | |
| 8996 | |
| 8997 /** | |
| 8998 * An object that maps header names to header values, first applying the | |
| 8999 * the value of `Content-Type` and then overlaying the headers specified | |
| 9000 * in the `headers` property. | |
| 9001 * | |
| 9002 * @return {Object} | |
| 9003 */ | |
| 9004 get requestHeaders() { | |
| 9005 var headers = {}; | |
| 9006 var contentType = this.contentType; | |
| 9007 if (contentType == null && (typeof this.body === 'string')) { | |
| 9008 contentType = 'application/x-www-form-urlencoded'; | |
| 9009 } | |
| 9010 if (contentType) { | |
| 9011 headers['content-type'] = contentType; | |
| 9012 } | |
| 9013 var header; | |
| 9014 | |
| 9015 if (this.headers instanceof Object) { | |
| 9016 for (header in this.headers) { | |
| 9017 headers[header] = this.headers[header].toString(); | |
| 9018 } | |
| 9019 } | |
| 9020 | |
| 9021 return headers; | |
| 9022 }, | |
| 9023 | |
| 9024 /** | |
| 9025 * Request options suitable for generating an `iron-request` instance based | |
| 9026 * on the current state of the `iron-ajax` instance's properties. | |
| 9027 * | |
| 9028 * @return {{ | |
| 9029 * url: string, | |
| 9030 * method: (string|undefined), | |
| 9031 * async: (boolean|undefined), | |
| 9032 * body: (ArrayBuffer|ArrayBufferView|Blob|Document|FormData|null|string|u
ndefined|Object), | |
| 9033 * headers: (Object|undefined), | |
| 9034 * handleAs: (string|undefined), | |
| 9035 * jsonPrefix: (string|undefined), | |
| 9036 * withCredentials: (boolean|undefined)}} | |
| 9037 */ | |
| 9038 toRequestOptions: function() { | |
| 9039 return { | |
| 9040 url: this.requestUrl || '', | |
| 9041 method: this.method, | |
| 9042 headers: this.requestHeaders, | |
| 9043 body: this.body, | |
| 9044 async: !this.sync, | |
| 9045 handleAs: this.handleAs, | |
| 9046 jsonPrefix: this.jsonPrefix, | |
| 9047 withCredentials: this.withCredentials, | |
| 9048 timeout: this.timeout | |
| 9049 }; | |
| 9050 }, | |
| 9051 | |
| 9052 /** | |
| 9053 * Performs an AJAX request to the specified URL. | |
| 9054 * | |
| 9055 * @return {!IronRequestElement} | |
| 9056 */ | |
| 9057 generateRequest: function() { | |
| 9058 var request = /** @type {!IronRequestElement} */ (document.createElement('
iron-request')); | |
| 9059 var requestOptions = this.toRequestOptions(); | |
| 9060 | |
| 9061 this.push('activeRequests', request); | |
| 9062 | |
| 9063 request.completes.then( | |
| 9064 this._boundHandleResponse | |
| 9065 ).catch( | |
| 9066 this._handleError.bind(this, request) | |
| 9067 ).then( | |
| 9068 this._discardRequest.bind(this, request) | |
| 9069 ); | |
| 9070 | |
| 9071 request.send(requestOptions); | |
| 9072 | |
| 9073 this._setLastRequest(request); | |
| 9074 this._setLoading(true); | |
| 9075 | |
| 9076 this.fire('request', { | |
| 9077 request: request, | |
| 9078 options: requestOptions | |
| 9079 }, {bubbles: this.bubbles}); | |
| 9080 | |
| 9081 this.fire('iron-ajax-request', { | |
| 9082 request: request, | |
| 9083 options: requestOptions | |
| 9084 }, {bubbles: this.bubbles}); | |
| 9085 | |
| 9086 return request; | |
| 9087 }, | |
| 9088 | |
| 9089 _handleResponse: function(request) { | |
| 9090 if (request === this.lastRequest) { | |
| 9091 this._setLastResponse(request.response); | |
| 9092 this._setLastError(null); | |
| 9093 this._setLoading(false); | |
| 9094 } | |
| 9095 this.fire('response', request, {bubbles: this.bubbles}); | |
| 9096 this.fire('iron-ajax-response', request, {bubbles: this.bubbles}); | |
| 9097 }, | |
| 9098 | |
| 9099 _handleError: function(request, error) { | |
| 9100 if (this.verbose) { | |
| 9101 Polymer.Base._error(error); | |
| 9102 } | |
| 9103 | |
| 9104 if (request === this.lastRequest) { | |
| 9105 this._setLastError({ | |
| 9106 request: request, | |
| 9107 error: error, | |
| 9108 status: request.xhr.status, | |
| 9109 statusText: request.xhr.statusText, | |
| 9110 response: request.xhr.response | |
| 9111 }); | |
| 9112 this._setLastResponse(null); | |
| 9113 this._setLoading(false); | |
| 9114 } | |
| 9115 | |
| 9116 // Tests fail if this goes after the normal this.fire('error', ...) | |
| 9117 this.fire('iron-ajax-error', { | |
| 9118 request: request, | |
| 9119 error: error | |
| 9120 }, {bubbles: this.bubbles}); | |
| 9121 | |
| 9122 this.fire('error', { | |
| 9123 request: request, | |
| 9124 error: error | |
| 9125 }, {bubbles: this.bubbles}); | |
| 9126 }, | |
| 9127 | |
| 9128 _discardRequest: function(request) { | |
| 9129 var requestIndex = this.activeRequests.indexOf(request); | |
| 9130 | |
| 9131 if (requestIndex > -1) { | |
| 9132 this.splice('activeRequests', requestIndex, 1); | |
| 9133 } | |
| 9134 }, | |
| 9135 | |
| 9136 _requestOptionsChanged: function() { | |
| 9137 this.debounce('generate-request', function() { | |
| 9138 if (this.url == null) { | |
| 9139 return; | |
| 9140 } | |
| 9141 | |
| 9142 if (this.auto) { | |
| 9143 this.generateRequest(); | |
| 9144 } | |
| 9145 }, this.debounceDuration); | |
| 9146 }, | |
| 9147 | |
| 9148 }); | |
| 9149 </script> | |
| 9150 | |
| 9151 | |
| 9152 <script> | 8150 <script> |
| 9153 Polymer.AppLayout = Polymer.AppLayout || {}; | 8151 Polymer.AppLayout = Polymer.AppLayout || {}; |
| 9154 | 8152 |
| 9155 Polymer.AppLayout._scrollEffects = Polymer.AppLayout._scrollEffects || {}; | 8153 Polymer.AppLayout._scrollEffects = Polymer.AppLayout._scrollEffects || {}; |
| 9156 | 8154 |
| 9157 Polymer.AppLayout.scrollTimingFunction = function easeOutQuad(t, b, c, d) { | 8155 Polymer.AppLayout.scrollTimingFunction = function easeOutQuad(t, b, c, d) { |
| 9158 t /= d; | 8156 t /= d; |
| 9159 return -c * t*(t-2) + b; | 8157 return -c * t*(t-2) + b; |
| 9160 }; | 8158 }; |
| 9161 | 8159 |
| (...skipping 5409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 14571 } | 13569 } |
| 14572 | 13570 |
| 14573 paper-spinner-lite { | 13571 paper-spinner-lite { |
| 14574 --paper-spinner-color: var(--google-yellow-500); | 13572 --paper-spinner-color: var(--google-yellow-500); |
| 14575 } | 13573 } |
| 14576 </style> | 13574 </style> |
| 14577 <app-header-layout> | 13575 <app-header-layout> |
| 14578 <app-header fixed=""> | 13576 <app-header fixed=""> |
| 14579 <app-toolbar> | 13577 <app-toolbar> |
| 14580 <div class="title left">[[name]]</div> | 13578 <div class="title left">[[name]]</div> |
| 14581 <paper-spinner-lite class="left" active="[[busy]]"></paper-spinner-lit
e> | 13579 <paper-spinner-lite class="left" active="[[_or(busy,_busy)]]"></paper-
spinner-lite> |
| 14582 | 13580 |
| 14583 <a class="left" href="/newui/">Home</a> | 13581 <a class="left" href="/newui/">Home</a> |
| 14584 <a class="left" href="/newui/botlist">Bot List</a> | 13582 <a class="left" href="/newui/botlist">Bot List</a> |
| 14585 <a class="left" href="/newui/tasklist">Task List</a> | 13583 <a class="left" href="/newui/tasklist">Task List</a> |
| 14586 <div class="flex"></div> | 13584 <div class="flex"></div> |
| 14587 <auth-signin class="right" client-id="[[client_id]]" auth-headers="{{a
uth_headers}}" signed-in="{{signed_in}}"> | 13585 <auth-signin class="right" client-id="[[client_id]]" auth-headers="{{a
uth_headers}}" signed-in="{{signed_in}}"> |
| 14588 </auth-signin> | 13586 </auth-signin> |
| 14589 </app-toolbar> | 13587 </app-toolbar> |
| 14590 </app-header> | 13588 </app-header> |
| 14591 <div class="main-content"> | 13589 <div class="main-content"> |
| 14592 <content></content> | 13590 <content></content> |
| 14593 </div> | 13591 </div> |
| 14594 </app-header-layout> | 13592 </app-header-layout> |
| 14595 | 13593 |
| 14596 </template> | 13594 </template> |
| 14597 <script> | 13595 <script> |
| 14598 Polymer({ | 13596 Polymer({ |
| 14599 is: 'swarming-app', | 13597 is: 'swarming-app', |
| 13598 |
| 13599 behaviors: [ |
| 13600 SwarmingBehaviors.CommonBehavior, |
| 13601 ], |
| 13602 |
| 14600 properties: { | 13603 properties: { |
| 13604 // input |
| 13605 busy: { |
| 13606 type: Boolean, |
| 13607 }, |
| 14601 client_id: { | 13608 client_id: { |
| 14602 type: String, | 13609 type: String, |
| 14603 }, | 13610 }, |
| 13611 name: { |
| 13612 type: String, |
| 13613 }, |
| 13614 // outputs |
| 14604 auth_headers: { | 13615 auth_headers: { |
| 14605 type: Object, | 13616 type: Object, |
| 14606 notify: true, | 13617 notify: true, |
| 13618 observer: "_loadPermissions" |
| 14607 }, | 13619 }, |
| 13620 |
| 13621 permissions: { |
| 13622 type: Object, |
| 13623 value: function() { |
| 13624 // If we aren't logged in, default to no permissions. |
| 13625 return {}; |
| 13626 }, |
| 13627 notify: true, |
| 13628 }, |
| 13629 |
| 14608 signed_in: { | 13630 signed_in: { |
| 14609 type: Boolean, | 13631 type: Boolean, |
| 14610 value: false, | 13632 value: false, |
| 14611 notify:true, | 13633 notify:true, |
| 14612 }, | 13634 }, |
| 14613 permissions: { | |
| 14614 type: Object, | |
| 14615 value: function() { | |
| 14616 // TODO(kjlubick): Make this call the whoami endpoint after signing
in. | |
| 14617 return { | |
| 14618 can_cancel_task: true, | |
| 14619 } | |
| 14620 }, | |
| 14621 notify: true, | |
| 14622 }, | |
| 14623 | 13635 |
| 14624 busy: { | 13636 // private |
| 13637 _busy: { |
| 14625 type: Boolean, | 13638 type: Boolean, |
| 14626 }, | 13639 value: false, |
| 14627 name: { | 13640 } |
| 14628 type: String, | 13641 |
| 14629 }, | 13642 }, |
| 13643 |
| 13644 _loadPermissions: function() { |
| 13645 this._getJsonAsync("permissions", "/_ah/api/swarming/v1/server/permissio
ns", |
| 13646 "_busy", this.auth_headers); |
| 14630 }, | 13647 }, |
| 14631 | 13648 |
| 14632 }); | 13649 }); |
| 14633 </script> | 13650 </script> |
| 14634 </dom-module> | 13651 </dom-module> |
| 14635 | 13652 |
| 14636 <dom-module id="swarming-app-style" assetpath="/res/imp/common/"> | 13653 <dom-module id="swarming-app-style" assetpath="/res/imp/common/"> |
| 14637 <style> | 13654 <style> |
| 14638 * { | 13655 * { |
| 14639 font-family: sans-serif; | 13656 font-family: sans-serif; |
| 14640 } | 13657 } |
| 14641 /* Only style anchor tags that are actually linking somewhere.*/ | 13658 /* Only style anchor tags that are actually linking somewhere.*/ |
| 14642 a[href] { | 13659 a[href] { |
| 14643 color: #1F78B4; | 13660 color: #1F78B4; |
| 14644 } | 13661 } |
| 14645 </style> | 13662 </style> |
| 14646 </dom-module> | 13663 </dom-module> |
| 14647 <dom-module id="swarming-index" assetpath="/res/imp/index/"> | 13664 <dom-module id="swarming-index" assetpath="/res/imp/index/"> |
| 14648 <template> | 13665 <template> |
| 14649 <style include="swarming-app-style"> | 13666 <style include="swarming-app-style"> |
| 14650 | 13667 .command { |
| 13668 font-family: monospace; |
| 13669 margin-bottom: 10px; |
| 13670 margin-top: 10px; |
| 13671 white-space: pre-wrap; |
| 13672 background-color: #f5f5f5; |
| 13673 border: 1px solid #ccc; |
| 13674 border-radius: 4px; |
| 13675 } |
| 14651 </style> | 13676 </style> |
| 14652 | 13677 |
| 14653 <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" name
="Swarming" busy="[[busy]]"> | 13678 <swarming-app client_id="[[client_id]]" auth_headers="{{auth_headers}}" perm
issions="{{_permissions}}" name="Swarming Server" busy="[[_busy]]"> |
| 14654 | 13679 |
| 14655 <iron-ajax id="request" url="/_ah/api/swarming/v1/server/details" headers=
"[[auth_headers]]" handle-as="json" last-response="{{serverDetails}}" loading="{
{busy}}"> | 13680 <h2>Service Status</h2> |
| 14656 </iron-ajax> | 13681 <div>Server Version: [[serverDetails.server_version]]</div> |
| 13682 <ul> |
| 13683 <li> |
| 13684 |
| 13685 <a href="/stats">Usage statistics</a> |
| 13686 </li> |
| 13687 <li> |
| 13688 <a href="/restricted/mapreduce/status">Map Reduce Jobs</a> |
| 13689 </li> |
| 13690 <li> |
| 13691 <a href$="[[_makeInstancesUrl(serverDetails,_project_id)]]">View versi
on's instances on Cloud Console</a> |
| 13692 </li> |
| 13693 <li> |
| 13694 <a></a><a href$="[[_makeErrorUrl(_project_id)]]">View server errors on
Cloud Console</a> |
| 13695 </li> |
| 13696 <li> |
| 13697 <a></a><a href$="[[_makeLogUrl(_project_id)]]">View logs for HTTP 5xx
on Cloud Console</a> |
| 13698 </li> |
| 13699 </ul> |
| 14657 | 13700 |
| 14658 <h1>HELLO WORLD</h1> | 13701 <h2>Configuration</h2> |
| 13702 <ul> |
| 13703 |
| 13704 <li> |
| 13705 <a href="/restricted/config">View server config</a> |
| 13706 </li> |
| 13707 <li> |
| 13708 <a href="/restricted/upload/bootstrap">View/upload bootstrap.py</a> |
| 13709 </li> |
| 13710 <li> |
| 13711 <a href="/restricted/upload/bot_config">View/upload bot_config.py</a> |
| 13712 </li> |
| 13713 <li> |
| 13714 <a href="/auth/groups">View/edit user groups</a> |
| 13715 </li> |
| 13716 </ul> |
| 14659 | 13717 |
| 14660 <div>Server Version: [[serverDetails.server_version]]</div> | 13718 <div hidden$="[[_cannotBootstrap(_permissions)]]"> |
| 13719 <h2>Bootstrapping a bot</h2> |
| 13720 To bootstrap a bot, run one of these (all links are valid for 1 hour): |
| 13721 <ol> |
| 13722 <li> |
| 13723 <strong> TL;DR; </strong> |
| 13724 <pre class="command">python -c "import urllib; exec urllib.urlopen('[[_host_ur
l]]/bootstrap?tok=[[_bootstrap_token]]').read()"</pre> |
| 13725 </li> |
| 13726 <li> |
| 13727 Escaped version to pass as a ssh argument: |
| 13728 <pre class="command">'python -c "import urllib; exec urllib.urlopen('"'[[_host
_url]]/bootstrap?tok=[[_bootstrap_token]]'"').read()"'</pre> |
| 13729 </li> |
| 13730 <li> |
| 13731 Manually: |
| 13732 <pre class="command" style="margin-bottom:0">mkdir bot; cd bot |
| 13733 rm -f swarming_bot.zip; curl -sSLOJ [[_host_url]]/bot_code?tok=[[_bootstrap_to
ken]] |
| 13734 python swarming_bot.zip</pre> |
| 13735 </li> |
| 13736 </ol> |
| 13737 </div> |
| 13738 |
| 13739 <h2>Stats</h2> |
| 13740 <div>TODO(kjlubick) add these in</div> |
| 13741 |
| 14661 | 13742 |
| 14662 </swarming-app> | 13743 </swarming-app> |
| 14663 | 13744 |
| 14664 </template> | 13745 </template> |
| 14665 <script> | 13746 <script> |
| 14666 Polymer({ | 13747 Polymer({ |
| 14667 is: 'swarming-index', | 13748 is: 'swarming-index', |
| 14668 | 13749 |
| 13750 behaviors: [ |
| 13751 SwarmingBehaviors.CommonBehavior, |
| 13752 ], |
| 13753 |
| 14669 properties: { | 13754 properties: { |
| 14670 client_id: { | 13755 client_id: { |
| 14671 type: String, | 13756 type: String, |
| 14672 }, | 13757 }, |
| 14673 | 13758 |
| 14674 auth_headers: { | 13759 auth_headers: { |
| 14675 type: Object, | 13760 type: Object, |
| 14676 observer: "signIn", | 13761 observer: "signIn", |
| 14677 }, | 13762 }, |
| 14678 | 13763 |
| 14679 serverDetails: { | 13764 serverDetails: { |
| 13765 type: Object, |
| 13766 }, |
| 13767 |
| 13768 _bootstrap_token: { |
| 14680 type: String, | 13769 type: String, |
| 13770 // TODO(kjlubick): fetch this from an API |
| 13771 value: "abc123", |
| 13772 }, |
| 13773 _busy: { |
| 13774 type: Boolean, |
| 13775 value: false, |
| 13776 }, |
| 13777 _host_url: { |
| 13778 type: String, |
| 13779 value: function() { |
| 13780 return location.origin; |
| 13781 }, |
| 13782 }, |
| 13783 _permissions: { |
| 13784 type: Object, |
| 13785 }, |
| 13786 _project_id: { |
| 13787 type: String, |
| 13788 value: function() { |
| 13789 var idx = location.hostname.indexOf(".appspot.com"); |
| 13790 return location.hostname.substring(0, idx); |
| 13791 }, |
| 14681 } | 13792 } |
| 14682 }, | 13793 }, |
| 14683 | 13794 |
| 14684 signIn: function(){ | 13795 signIn: function(){ |
| 14685 this.$.request.generateRequest(); | 13796 this._getJsonAsync("serverDetails", "/_ah/api/swarming/v1/server/details
", |
| 13797 "_busy", this.auth_headers); |
| 13798 }, |
| 13799 |
| 13800 _cannotBootstrap: function(permissions) { |
| 13801 return !(permissions && permissions.get_bootstrap_token); |
| 13802 }, |
| 13803 |
| 13804 _makeInstancesUrl: function(details, project_id) { |
| 13805 return "https://console.cloud.google.com/appengine/instances?project="+ |
| 13806 project_id+"&versionId="+details.server_version; |
| 13807 }, |
| 13808 |
| 13809 _makeErrorUrl: function(project_id) { |
| 13810 return "https://console.cloud.google.com/errors?project="+ |
| 13811 project_id; |
| 13812 }, |
| 13813 |
| 13814 _makeLogUrl: function(project_id) { |
| 13815 return "https://pantheon.corp.google.com/logs/viewer?filters=text:status
:500..599&project="+ |
| 13816 project_id; |
| 14686 }, | 13817 }, |
| 14687 | 13818 |
| 14688 }); | 13819 }); |
| 14689 </script> | 13820 </script> |
| 14690 </dom-module><script> | 13821 </dom-module><dom-module id="dynamic-table-style" assetpath="/res/imp/common/"> |
| 14691 window.SwarmingBehaviors = window.SwarmingBehaviors || {}; | |
| 14692 (function(){ | |
| 14693 // This behavior wraps up all the shared swarming functionality. | |
| 14694 SwarmingBehaviors.CommonBehavior = { | |
| 14695 | |
| 14696 // _getJsonAsync makes an XHR to a url, parses the response as JSON | |
| 14697 // and sticks the resulting object into the property with the name given | |
| 14698 // by "bindTo". If busy is defined, the property with that name will be | |
| 14699 // set to true while the request is in flight and false afterwards. | |
| 14700 // request headers (e.g. authentication) and query params will be used if | |
| 14701 // provided. Query params is an object like {String:Array<String>}. On | |
| 14702 // error, bindTo will be set to false. It is not set to undefined | |
| 14703 // because computed values in Polymer don't fire if a property is | |
| 14704 // undefined. Clients should check that bindTo is not falsey. | |
| 14705 _getJsonAsync: function(bindTo, url, busy, headers, params) { | |
| 14706 if (!bindTo || !url) { | |
| 14707 console.log("Need at least a polymer element to bind to and a url"); | |
| 14708 return; | |
| 14709 } | |
| 14710 if (busy) { | |
| 14711 this.set(busy, true); | |
| 14712 } | |
| 14713 url = url + "?" + sk.query.fromParamSet(params); | |
| 14714 sk.request("GET", url, "", headers).then(JSON.parse).then(function(json)
{ | |
| 14715 this.set(bindTo, json); | |
| 14716 if (busy) { | |
| 14717 this.set(busy, false); | |
| 14718 } | |
| 14719 }.bind(this)).catch(function(reason){ | |
| 14720 console.log("Reason for failure of request to " + url, reason); | |
| 14721 this.set(bindTo, false); | |
| 14722 if (busy) { | |
| 14723 this.set(busy, false); | |
| 14724 } | |
| 14725 }.bind(this)); | |
| 14726 }, | |
| 14727 | |
| 14728 _not: function(a) { | |
| 14729 return !a; | |
| 14730 }, | |
| 14731 | |
| 14732 _or: function() { | |
| 14733 var result = false; | |
| 14734 // can't use .foreach, as arguments isn't really an Array. | |
| 14735 for (var i = 0; i < arguments.length; i++) { | |
| 14736 result = result || arguments[i]; | |
| 14737 } | |
| 14738 return result; | |
| 14739 }, | |
| 14740 }; | |
| 14741 })(); | |
| 14742 </script> | |
| 14743 <dom-module id="dynamic-table-style" assetpath="/res/imp/common/"> | |
| 14744 <template> | 13822 <template> |
| 14745 <style> | 13823 <style> |
| 14746 table { | 13824 table { |
| 14747 border-collapse: collapse; | 13825 border-collapse: collapse; |
| 14748 margin-left: 5px; | 13826 margin-left: 5px; |
| 14749 } | 13827 } |
| 14750 td, th { | 13828 td, th { |
| 14751 border: 1px solid #DDD; | 13829 border: 1px solid #DDD; |
| 14752 padding: 5px; | 13830 padding: 5px; |
| 14753 } | 13831 } |
| (...skipping 10471 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 25225 def = "none"; | 24303 def = "none"; |
| 25226 } | 24304 } |
| 25227 var retVal = this._tag(task, col) || task[col] || [def]; | 24305 var retVal = this._tag(task, col) || task[col] || [def]; |
| 25228 if (!Array.isArray(retVal)) { | 24306 if (!Array.isArray(retVal)) { |
| 25229 return [retVal]; | 24307 return [retVal]; |
| 25230 } | 24308 } |
| 25231 return retVal; | 24309 return retVal; |
| 25232 }, | 24310 }, |
| 25233 | 24311 |
| 25234 _cannotCancel: function(task, permissions) { | 24312 _cannotCancel: function(task, permissions) { |
| 25235 return !(permissions && permissions.can_cancel_task && | 24313 return !(permissions && permissions.cancel_task && |
| 25236 this._column("state", task) === "PENDING"); | 24314 this._column("state", task) === "PENDING"); |
| 25237 }, | 24315 }, |
| 25238 | 24316 |
| 25239 _cancelTask: function(e) { | 24317 _cancelTask: function(e) { |
| 25240 var task = e.model.task; | 24318 var task = e.model.task; |
| 25241 if (!task || !task.task_id) { | 24319 if (!task || !task.task_id) { |
| 25242 console.log("Missing task info", task); | 24320 console.log("Missing task info", task); |
| 25243 return | 24321 return |
| 25244 } | 24322 } |
| 25245 var id = task.task_id | 24323 var id = task.task_id |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 25294 if (state === "RUNNING" || state === "PENDING") { | 24372 if (state === "RUNNING" || state === "PENDING") { |
| 25295 return "pending"; | 24373 return "pending"; |
| 25296 } | 24374 } |
| 25297 return ""; | 24375 return ""; |
| 25298 } | 24376 } |
| 25299 | 24377 |
| 25300 }); | 24378 }); |
| 25301 })(); | 24379 })(); |
| 25302 </script> | 24380 </script> |
| 25303 </dom-module></div></body></html> | 24381 </dom-module></div></body></html> |
| OLD | NEW |