Index: third_party/WebKit/Source/devtools/front_end/network/NetworkTimeCalculator.js |
diff --git a/third_party/WebKit/Source/devtools/front_end/network/NetworkTimeCalculator.js b/third_party/WebKit/Source/devtools/front_end/network/NetworkTimeCalculator.js |
index 7717bc748da5f5ee34cb7f937d31c356be35a335..90b51db989ee6fd1b4267eba4ab1b38a09da85bf 100644 |
--- a/third_party/WebKit/Source/devtools/front_end/network/NetworkTimeCalculator.js |
+++ b/third_party/WebKit/Source/devtools/front_end/network/NetworkTimeCalculator.js |
@@ -27,422 +27,383 @@ |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
- |
/** |
- * @constructor |
- * @param {number} minimum |
- * @param {number} maximum |
+ * @unrestricted |
*/ |
-WebInspector.NetworkTimeBoundary = function(minimum, maximum) |
-{ |
+WebInspector.NetworkTimeBoundary = class { |
+ /** |
+ * @param {number} minimum |
+ * @param {number} maximum |
+ */ |
+ constructor(minimum, maximum) { |
this.minimum = minimum; |
this.maximum = maximum; |
-}; |
- |
-WebInspector.NetworkTimeBoundary.prototype = { |
- /** |
- * @param {!WebInspector.NetworkTimeBoundary} other |
- * @return {boolean} |
- */ |
- equals: function(other) |
- { |
- return (this.minimum === other.minimum) && (this.maximum === other.maximum); |
- } |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.NetworkTimeBoundary} other |
+ * @return {boolean} |
+ */ |
+ equals(other) { |
+ return (this.minimum === other.minimum) && (this.maximum === other.maximum); |
+ } |
}; |
/** |
- * @constructor |
- * @extends {WebInspector.Object} |
* @implements {WebInspector.TimelineGrid.Calculator} |
+ * @unrestricted |
*/ |
-WebInspector.NetworkTimeCalculator = function(startAtZero) |
-{ |
+WebInspector.NetworkTimeCalculator = class extends WebInspector.Object { |
+ constructor(startAtZero) { |
+ super(); |
this.startAtZero = startAtZero; |
this._boundryChangedEventThrottler = new WebInspector.Throttler(0); |
/** @type {?WebInspector.NetworkTimeBoundary} */ |
this._window = null; |
+ } |
+ |
+ /** |
+ * @param {?WebInspector.NetworkTimeBoundary} window |
+ */ |
+ setWindow(window) { |
+ this._window = window; |
+ this._boundaryChanged(); |
+ } |
+ |
+ setInitialUserFriendlyBoundaries() { |
+ this._minimumBoundary = 0; |
+ this._maximumBoundary = 1; |
+ } |
+ |
+ /** |
+ * @override |
+ * @return {number} |
+ */ |
+ paddingLeft() { |
+ return 0; |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {number} time |
+ * @return {number} |
+ */ |
+ computePosition(time) { |
+ return (time - this.minimumBoundary()) / this.boundarySpan() * this._workingArea; |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {number} value |
+ * @param {number=} precision |
+ * @return {string} |
+ */ |
+ formatValue(value, precision) { |
+ return Number.secondsToString(value, !!precision); |
+ } |
+ |
+ /** |
+ * @override |
+ * @return {number} |
+ */ |
+ minimumBoundary() { |
+ return this._window ? this._window.minimum : this._minimumBoundary; |
+ } |
+ |
+ /** |
+ * @override |
+ * @return {number} |
+ */ |
+ zeroTime() { |
+ return this._minimumBoundary; |
+ } |
+ |
+ /** |
+ * @override |
+ * @return {number} |
+ */ |
+ maximumBoundary() { |
+ return this._window ? this._window.maximum : this._maximumBoundary; |
+ } |
+ |
+ /** |
+ * @return {!WebInspector.NetworkTimeBoundary} |
+ */ |
+ boundary() { |
+ return new WebInspector.NetworkTimeBoundary(this.minimumBoundary(), this.maximumBoundary()); |
+ } |
+ |
+ /** |
+ * @override |
+ * @return {number} |
+ */ |
+ boundarySpan() { |
+ return this.maximumBoundary() - this.minimumBoundary(); |
+ } |
+ |
+ reset() { |
+ delete this._minimumBoundary; |
+ delete this._maximumBoundary; |
+ this._boundaryChanged(); |
+ } |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ _value(item) { |
+ return 0; |
+ } |
+ |
+ /** |
+ * @param {number} clientWidth |
+ */ |
+ setDisplayWindow(clientWidth) { |
+ this._workingArea = clientWidth; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.NetworkRequest} request |
+ * @return {!{start: number, middle: number, end: number}} |
+ */ |
+ computeBarGraphPercentages(request) { |
+ if (request.startTime !== -1) |
+ var start = ((request.startTime - this.minimumBoundary()) / this.boundarySpan()) * 100; |
+ else |
+ var start = 0; |
+ |
+ if (request.responseReceivedTime !== -1) |
+ var middle = ((request.responseReceivedTime - this.minimumBoundary()) / this.boundarySpan()) * 100; |
+ else |
+ var middle = (this.startAtZero ? start : 100); |
+ |
+ if (request.endTime !== -1) |
+ var end = ((request.endTime - this.minimumBoundary()) / this.boundarySpan()) * 100; |
+ else |
+ var end = (this.startAtZero ? middle : 100); |
+ |
+ if (this.startAtZero) { |
+ end -= start; |
+ middle -= start; |
+ start = 0; |
+ } |
+ |
+ return {start: start, middle: middle, end: end}; |
+ } |
+ |
+ /** |
+ * @param {number} eventTime |
+ * @return {number} |
+ */ |
+ computePercentageFromEventTime(eventTime) { |
+ // This function computes a percentage in terms of the total loading time |
+ // of a specific event. If startAtZero is set, then this is useless, and we |
+ // want to return 0. |
+ if (eventTime !== -1 && !this.startAtZero) |
+ return ((eventTime - this.minimumBoundary()) / this.boundarySpan()) * 100; |
+ |
+ return 0; |
+ } |
+ |
+ /** |
+ * @param {number} percentage |
+ * @return {number} |
+ */ |
+ percentageToTime(percentage) { |
+ return percentage * this.boundarySpan() / 100 + this.minimumBoundary(); |
+ } |
+ |
+ _boundaryChanged() { |
+ this._boundryChangedEventThrottler.schedule(dispatchEvent.bind(this)); |
+ |
+ /** |
+ * @return {!Promise.<undefined>} |
+ * @this {WebInspector.NetworkTimeCalculator} |
+ */ |
+ function dispatchEvent() { |
+ this.dispatchEventToListeners(WebInspector.NetworkTimeCalculator.Events.BoundariesChanged); |
+ return Promise.resolve(); |
+ } |
+ } |
+ |
+ /** |
+ * @param {number} eventTime |
+ */ |
+ updateBoundariesForEventTime(eventTime) { |
+ if (eventTime === -1 || this.startAtZero) |
+ return; |
+ |
+ if (this._maximumBoundary === undefined || eventTime > this._maximumBoundary) { |
+ this._maximumBoundary = eventTime; |
+ this._boundaryChanged(); |
+ } |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.NetworkRequest} request |
+ * @return {!{left: string, right: string, tooltip: (string|undefined)}} |
+ */ |
+ computeBarGraphLabels(request) { |
+ var rightLabel = ''; |
+ if (request.responseReceivedTime !== -1 && request.endTime !== -1) |
+ rightLabel = Number.secondsToString(request.endTime - request.responseReceivedTime); |
+ |
+ var hasLatency = request.latency > 0; |
+ if (hasLatency) |
+ var leftLabel = Number.secondsToString(request.latency); |
+ else |
+ var leftLabel = rightLabel; |
+ |
+ if (request.timing) |
+ return {left: leftLabel, right: rightLabel}; |
+ |
+ if (hasLatency && rightLabel) { |
+ var total = Number.secondsToString(request.duration); |
+ var tooltip = WebInspector.NetworkTimeCalculator._latencyDownloadTotalFormat.format(leftLabel, rightLabel, total); |
+ } else if (hasLatency) { |
+ var tooltip = WebInspector.NetworkTimeCalculator._latencyFormat.format(leftLabel); |
+ } else if (rightLabel) { |
+ var tooltip = WebInspector.NetworkTimeCalculator._downloadFormat.format(rightLabel); |
+ } |
+ |
+ if (request.fetchedViaServiceWorker) |
+ tooltip = WebInspector.NetworkTimeCalculator._fromServiceWorkerFormat.format(tooltip); |
+ else if (request.cached()) |
+ tooltip = WebInspector.NetworkTimeCalculator._fromCacheFormat.format(tooltip); |
+ return {left: leftLabel, right: rightLabel, tooltip: tooltip}; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.NetworkRequest} request |
+ */ |
+ updateBoundaries(request) { |
+ var lowerBound = this._lowerBound(request); |
+ var upperBound = this._upperBound(request); |
+ var changed = false; |
+ if (lowerBound !== -1 || this.startAtZero) |
+ changed = this._extendBoundariesToIncludeTimestamp(this.startAtZero ? 0 : lowerBound); |
+ if (upperBound !== -1) |
+ changed = this._extendBoundariesToIncludeTimestamp(upperBound) || changed; |
+ if (changed) |
+ this._boundaryChanged(); |
+ } |
+ |
+ /** |
+ * @param {number} timestamp |
+ * @return {boolean} |
+ */ |
+ _extendBoundariesToIncludeTimestamp(timestamp) { |
+ var previousMinimumBoundary = this._minimumBoundary; |
+ var previousMaximumBoundary = this._maximumBoundary; |
+ if (typeof this._minimumBoundary === 'undefined' || typeof this._maximumBoundary === 'undefined') { |
+ this._minimumBoundary = timestamp; |
+ this._maximumBoundary = timestamp + 1; |
+ } else { |
+ this._minimumBoundary = Math.min(timestamp, this._minimumBoundary); |
+ this._maximumBoundary = Math.max(timestamp, this._minimumBoundary + 1, this._maximumBoundary); |
+ } |
+ return previousMinimumBoundary !== this._minimumBoundary || previousMaximumBoundary !== this._maximumBoundary; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.NetworkRequest} request |
+ * @return {number} |
+ */ |
+ _lowerBound(request) { |
+ return 0; |
+ } |
+ |
+ /** |
+ * @param {!WebInspector.NetworkRequest} request |
+ * @return {number} |
+ */ |
+ _upperBound(request) { |
+ return 0; |
+ } |
}; |
/** @enum {symbol} */ |
WebInspector.NetworkTimeCalculator.Events = { |
- BoundariesChanged: Symbol("BoundariesChanged") |
+ BoundariesChanged: Symbol('BoundariesChanged') |
}; |
/** @type {!WebInspector.UIStringFormat} */ |
-WebInspector.NetworkTimeCalculator._latencyDownloadTotalFormat = new WebInspector.UIStringFormat("%s latency, %s download (%s total)"); |
+WebInspector.NetworkTimeCalculator._latencyDownloadTotalFormat = |
+ new WebInspector.UIStringFormat('%s latency, %s download (%s total)'); |
/** @type {!WebInspector.UIStringFormat} */ |
-WebInspector.NetworkTimeCalculator._latencyFormat = new WebInspector.UIStringFormat("%s latency"); |
+WebInspector.NetworkTimeCalculator._latencyFormat = new WebInspector.UIStringFormat('%s latency'); |
/** @type {!WebInspector.UIStringFormat} */ |
-WebInspector.NetworkTimeCalculator._downloadFormat = new WebInspector.UIStringFormat("%s download"); |
+WebInspector.NetworkTimeCalculator._downloadFormat = new WebInspector.UIStringFormat('%s download'); |
/** @type {!WebInspector.UIStringFormat} */ |
-WebInspector.NetworkTimeCalculator._fromServiceWorkerFormat = new WebInspector.UIStringFormat("%s (from ServiceWorker)"); |
+WebInspector.NetworkTimeCalculator._fromServiceWorkerFormat = |
+ new WebInspector.UIStringFormat('%s (from ServiceWorker)'); |
/** @type {!WebInspector.UIStringFormat} */ |
-WebInspector.NetworkTimeCalculator._fromCacheFormat = new WebInspector.UIStringFormat("%s (from cache)"); |
- |
-WebInspector.NetworkTimeCalculator.prototype = { |
- /** |
- * @param {?WebInspector.NetworkTimeBoundary} window |
- */ |
- setWindow: function(window) |
- { |
- this._window = window; |
- this._boundaryChanged(); |
- }, |
- |
- setInitialUserFriendlyBoundaries: function() |
- { |
- this._minimumBoundary = 0; |
- this._maximumBoundary = 1; |
- }, |
- |
- /** |
- * @override |
- * @return {number} |
- */ |
- paddingLeft: function() |
- { |
- return 0; |
- }, |
- |
- /** |
- * @override |
- * @param {number} time |
- * @return {number} |
- */ |
- computePosition: function(time) |
- { |
- return (time - this.minimumBoundary()) / this.boundarySpan() * this._workingArea; |
- }, |
- |
- /** |
- * @override |
- * @param {number} value |
- * @param {number=} precision |
- * @return {string} |
- */ |
- formatValue: function(value, precision) |
- { |
- return Number.secondsToString(value, !!precision); |
- }, |
- |
- /** |
- * @override |
- * @return {number} |
- */ |
- minimumBoundary: function() |
- { |
- return this._window ? this._window.minimum : this._minimumBoundary; |
- }, |
- |
- /** |
- * @override |
- * @return {number} |
- */ |
- zeroTime: function() |
- { |
- return this._minimumBoundary; |
- }, |
- |
- /** |
- * @override |
- * @return {number} |
- */ |
- maximumBoundary: function() |
- { |
- return this._window ? this._window.maximum : this._maximumBoundary; |
- }, |
- |
- /** |
- * @return {!WebInspector.NetworkTimeBoundary} |
- */ |
- boundary: function() |
- { |
- return new WebInspector.NetworkTimeBoundary(this.minimumBoundary(), this.maximumBoundary()); |
- }, |
- |
- /** |
- * @override |
- * @return {number} |
- */ |
- boundarySpan: function() |
- { |
- return this.maximumBoundary() - this.minimumBoundary(); |
- }, |
- |
- reset: function() |
- { |
- delete this._minimumBoundary; |
- delete this._maximumBoundary; |
- this._boundaryChanged(); |
- }, |
- |
- /** |
- * @return {number} |
- */ |
- _value: function(item) |
- { |
- return 0; |
- }, |
- |
- /** |
- * @param {number} clientWidth |
- */ |
- setDisplayWindow: function(clientWidth) |
- { |
- this._workingArea = clientWidth; |
- }, |
- |
- /** |
- * @param {!WebInspector.NetworkRequest} request |
- * @return {!{start: number, middle: number, end: number}} |
- */ |
- computeBarGraphPercentages: function(request) |
- { |
- if (request.startTime !== -1) |
- var start = ((request.startTime - this.minimumBoundary()) / this.boundarySpan()) * 100; |
- else |
- var start = 0; |
- |
- if (request.responseReceivedTime !== -1) |
- var middle = ((request.responseReceivedTime - this.minimumBoundary()) / this.boundarySpan()) * 100; |
- else |
- var middle = (this.startAtZero ? start : 100); |
- |
- if (request.endTime !== -1) |
- var end = ((request.endTime - this.minimumBoundary()) / this.boundarySpan()) * 100; |
- else |
- var end = (this.startAtZero ? middle : 100); |
- |
- if (this.startAtZero) { |
- end -= start; |
- middle -= start; |
- start = 0; |
- } |
- |
- return {start: start, middle: middle, end: end}; |
- }, |
- |
- /** |
- * @param {number} eventTime |
- * @return {number} |
- */ |
- computePercentageFromEventTime: function(eventTime) |
- { |
- // This function computes a percentage in terms of the total loading time |
- // of a specific event. If startAtZero is set, then this is useless, and we |
- // want to return 0. |
- if (eventTime !== -1 && !this.startAtZero) |
- return ((eventTime - this.minimumBoundary()) / this.boundarySpan()) * 100; |
- |
- return 0; |
- }, |
- |
- /** |
- * @param {number} percentage |
- * @return {number} |
- */ |
- percentageToTime: function(percentage) |
- { |
- return percentage * this.boundarySpan() / 100 + this.minimumBoundary(); |
- }, |
- |
- _boundaryChanged: function() |
- { |
- this._boundryChangedEventThrottler.schedule(dispatchEvent.bind(this)); |
- |
- /** |
- * @return {!Promise.<undefined>} |
- * @this {WebInspector.NetworkTimeCalculator} |
- */ |
- function dispatchEvent() |
- { |
- this.dispatchEventToListeners(WebInspector.NetworkTimeCalculator.Events.BoundariesChanged); |
- return Promise.resolve(); |
- } |
- }, |
- |
- /** |
- * @param {number} eventTime |
- */ |
- updateBoundariesForEventTime: function(eventTime) |
- { |
- if (eventTime === -1 || this.startAtZero) |
- return; |
- |
- if (this._maximumBoundary === undefined || eventTime > this._maximumBoundary) { |
- this._maximumBoundary = eventTime; |
- this._boundaryChanged(); |
- } |
- }, |
- |
- /** |
- * @param {!WebInspector.NetworkRequest} request |
- * @return {!{left: string, right: string, tooltip: (string|undefined)}} |
- */ |
- computeBarGraphLabels: function(request) |
- { |
- var rightLabel = ""; |
- if (request.responseReceivedTime !== -1 && request.endTime !== -1) |
- rightLabel = Number.secondsToString(request.endTime - request.responseReceivedTime); |
- |
- var hasLatency = request.latency > 0; |
- if (hasLatency) |
- var leftLabel = Number.secondsToString(request.latency); |
- else |
- var leftLabel = rightLabel; |
- |
- if (request.timing) |
- return {left: leftLabel, right: rightLabel}; |
- |
- if (hasLatency && rightLabel) { |
- var total = Number.secondsToString(request.duration); |
- var tooltip = WebInspector.NetworkTimeCalculator._latencyDownloadTotalFormat.format(leftLabel, rightLabel, total); |
- } else if (hasLatency) { |
- var tooltip = WebInspector.NetworkTimeCalculator._latencyFormat.format(leftLabel); |
- } else if (rightLabel) { |
- var tooltip = WebInspector.NetworkTimeCalculator._downloadFormat.format(rightLabel); |
- } |
- |
- if (request.fetchedViaServiceWorker) |
- tooltip = WebInspector.NetworkTimeCalculator._fromServiceWorkerFormat.format(tooltip); |
- else if (request.cached()) |
- tooltip = WebInspector.NetworkTimeCalculator._fromCacheFormat.format(tooltip); |
- return {left: leftLabel, right: rightLabel, tooltip: tooltip}; |
- }, |
- |
- /** |
- * @param {!WebInspector.NetworkRequest} request |
- */ |
- updateBoundaries: function(request) |
- { |
- var lowerBound = this._lowerBound(request); |
- var upperBound = this._upperBound(request); |
- var changed = false; |
- if (lowerBound !== -1 || this.startAtZero) |
- changed = this._extendBoundariesToIncludeTimestamp(this.startAtZero ? 0 : lowerBound); |
- if (upperBound !== -1) |
- changed = this._extendBoundariesToIncludeTimestamp(upperBound) || changed; |
- if (changed) |
- this._boundaryChanged(); |
- }, |
- |
- /** |
- * @param {number} timestamp |
- * @return {boolean} |
- */ |
- _extendBoundariesToIncludeTimestamp: function(timestamp) |
- { |
- var previousMinimumBoundary = this._minimumBoundary; |
- var previousMaximumBoundary = this._maximumBoundary; |
- if (typeof this._minimumBoundary === "undefined" || typeof this._maximumBoundary === "undefined") { |
- this._minimumBoundary = timestamp; |
- this._maximumBoundary = timestamp + 1; |
- } else { |
- this._minimumBoundary = Math.min(timestamp, this._minimumBoundary); |
- this._maximumBoundary = Math.max(timestamp, this._minimumBoundary + 1, this._maximumBoundary); |
- } |
- return previousMinimumBoundary !== this._minimumBoundary || previousMaximumBoundary !== this._maximumBoundary; |
- }, |
- |
- /** |
- * @param {!WebInspector.NetworkRequest} request |
- * @return {number} |
- */ |
- _lowerBound: function(request) |
- { |
- return 0; |
- }, |
- |
- /** |
- * @param {!WebInspector.NetworkRequest} request |
- * @return {number} |
- */ |
- _upperBound: function(request) |
- { |
- return 0; |
- }, |
- |
- __proto__: WebInspector.Object.prototype |
-}; |
+WebInspector.NetworkTimeCalculator._fromCacheFormat = new WebInspector.UIStringFormat('%s (from cache)'); |
/** |
- * @constructor |
- * @extends {WebInspector.NetworkTimeCalculator} |
+ * @unrestricted |
*/ |
-WebInspector.NetworkTransferTimeCalculator = function() |
-{ |
- WebInspector.NetworkTimeCalculator.call(this, false); |
-}; |
- |
-WebInspector.NetworkTransferTimeCalculator.prototype = { |
- /** |
- * @override |
- * @param {number} value |
- * @param {number=} precision |
- * @return {string} |
- */ |
- formatValue: function(value, precision) |
- { |
- return Number.secondsToString(value - this.zeroTime(), !!precision); |
- }, |
- |
- /** |
- * @override |
- * @param {!WebInspector.NetworkRequest} request |
- * @return {number} |
- */ |
- _lowerBound: function(request) |
- { |
- return request.issueTime(); |
- }, |
- |
- /** |
- * @override |
- * @param {!WebInspector.NetworkRequest} request |
- * @return {number} |
- */ |
- _upperBound: function(request) |
- { |
- return request.endTime; |
- }, |
- |
- __proto__: WebInspector.NetworkTimeCalculator.prototype |
+WebInspector.NetworkTransferTimeCalculator = class extends WebInspector.NetworkTimeCalculator { |
+ constructor() { |
+ super(false); |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {number} value |
+ * @param {number=} precision |
+ * @return {string} |
+ */ |
+ formatValue(value, precision) { |
+ return Number.secondsToString(value - this.zeroTime(), !!precision); |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {!WebInspector.NetworkRequest} request |
+ * @return {number} |
+ */ |
+ _lowerBound(request) { |
+ return request.issueTime(); |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {!WebInspector.NetworkRequest} request |
+ * @return {number} |
+ */ |
+ _upperBound(request) { |
+ return request.endTime; |
+ } |
}; |
/** |
- * @constructor |
- * @extends {WebInspector.NetworkTimeCalculator} |
+ * @unrestricted |
*/ |
-WebInspector.NetworkTransferDurationCalculator = function() |
-{ |
- WebInspector.NetworkTimeCalculator.call(this, true); |
-}; |
- |
-WebInspector.NetworkTransferDurationCalculator.prototype = { |
- /** |
- * @override |
- * @param {number} value |
- * @param {number=} precision |
- * @return {string} |
- */ |
- formatValue: function(value, precision) |
- { |
- return Number.secondsToString(value, !!precision); |
- }, |
- |
- /** |
- * @override |
- * @param {!WebInspector.NetworkRequest} request |
- * @return {number} |
- */ |
- _upperBound: function(request) |
- { |
- return request.duration; |
- }, |
- |
- __proto__: WebInspector.NetworkTimeCalculator.prototype |
+WebInspector.NetworkTransferDurationCalculator = class extends WebInspector.NetworkTimeCalculator { |
+ constructor() { |
+ super(true); |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {number} value |
+ * @param {number=} precision |
+ * @return {string} |
+ */ |
+ formatValue(value, precision) { |
+ return Number.secondsToString(value, !!precision); |
+ } |
+ |
+ /** |
+ * @override |
+ * @param {!WebInspector.NetworkRequest} request |
+ * @return {number} |
+ */ |
+ _upperBound(request) { |
+ return request.duration; |
+ } |
}; |