| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| 11 * copyright notice, this list of conditions and the following disclaimer | 11 * copyright notice, this list of conditions and the following disclaimer |
| 12 * in the documentation and/or other materials provided with the | 12 * in the documentation and/or other materials provided with the |
| 13 * distribution. | 13 * distribution. |
| 14 * * Neither the name of Google Inc. nor the names of its | 14 * * Neither the name of Google Inc. nor the names of its |
| 15 * contributors may be used to endorse or promote products derived from | 15 * contributors may be used to endorse or promote products derived from |
| 16 * this software without specific prior written permission. | 16 * this software without specific prior written permission. |
| 17 * | 17 * |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | |
| 31 /** | 30 /** |
| 32 * @constructor | 31 * @unrestricted |
| 33 * @extends {WebInspector.VBox} | |
| 34 * @param {!WebInspector.NetworkRequest} request | |
| 35 * @param {!WebInspector.NetworkTimeCalculator} calculator | |
| 36 */ | 32 */ |
| 37 WebInspector.RequestTimingView = function(request, calculator) | 33 WebInspector.RequestTimingView = class extends WebInspector.VBox { |
| 38 { | 34 /** |
| 39 WebInspector.VBox.call(this); | 35 * @param {!WebInspector.NetworkRequest} request |
| 40 this.element.classList.add("resource-timing-view"); | 36 * @param {!WebInspector.NetworkTimeCalculator} calculator |
| 37 */ |
| 38 constructor(request, calculator) { |
| 39 super(); |
| 40 this.element.classList.add('resource-timing-view'); |
| 41 | 41 |
| 42 this._request = request; | 42 this._request = request; |
| 43 this._calculator = calculator; | 43 this._calculator = calculator; |
| 44 }; | 44 } |
| 45 | 45 |
| 46 WebInspector.RequestTimingView.prototype = { | 46 /** |
| 47 wasShown: function() | 47 * @param {!WebInspector.RequestTimeRangeNames} name |
| 48 { | 48 * @return {string} |
| 49 this._request.addEventListener(WebInspector.NetworkRequest.Events.Timing
Changed, this._refresh, this); | 49 */ |
| 50 this._request.addEventListener(WebInspector.NetworkRequest.Events.Finish
edLoading, this._refresh, this); | 50 static _timeRangeTitle(name) { |
| 51 this._calculator.addEventListener(WebInspector.NetworkTimeCalculator.Eve
nts.BoundariesChanged, this._refresh, this); | 51 switch (name) { |
| 52 this._refresh(); | 52 case WebInspector.RequestTimeRangeNames.Push: |
| 53 }, | 53 return WebInspector.UIString('Receiving Push'); |
| 54 case WebInspector.RequestTimeRangeNames.Queueing: |
| 55 return WebInspector.UIString('Queueing'); |
| 56 case WebInspector.RequestTimeRangeNames.Blocking: |
| 57 return WebInspector.UIString('Stalled'); |
| 58 case WebInspector.RequestTimeRangeNames.Connecting: |
| 59 return WebInspector.UIString('Initial connection'); |
| 60 case WebInspector.RequestTimeRangeNames.DNS: |
| 61 return WebInspector.UIString('DNS Lookup'); |
| 62 case WebInspector.RequestTimeRangeNames.Proxy: |
| 63 return WebInspector.UIString('Proxy negotiation'); |
| 64 case WebInspector.RequestTimeRangeNames.ReceivingPush: |
| 65 return WebInspector.UIString('Reading Push'); |
| 66 case WebInspector.RequestTimeRangeNames.Receiving: |
| 67 return WebInspector.UIString('Content Download'); |
| 68 case WebInspector.RequestTimeRangeNames.Sending: |
| 69 return WebInspector.UIString('Request sent'); |
| 70 case WebInspector.RequestTimeRangeNames.ServiceWorker: |
| 71 return WebInspector.UIString('Request to ServiceWorker'); |
| 72 case WebInspector.RequestTimeRangeNames.ServiceWorkerPreparation: |
| 73 return WebInspector.UIString('ServiceWorker Preparation'); |
| 74 case WebInspector.RequestTimeRangeNames.SSL: |
| 75 return WebInspector.UIString('SSL'); |
| 76 case WebInspector.RequestTimeRangeNames.Total: |
| 77 return WebInspector.UIString('Total'); |
| 78 case WebInspector.RequestTimeRangeNames.Waiting: |
| 79 return WebInspector.UIString('Waiting (TTFB)'); |
| 80 default: |
| 81 return WebInspector.UIString(name); |
| 82 } |
| 83 } |
| 54 | 84 |
| 55 willHide: function() | 85 /** |
| 56 { | 86 * @param {!WebInspector.NetworkRequest} request |
| 57 this._request.removeEventListener(WebInspector.NetworkRequest.Events.Tim
ingChanged, this._refresh, this); | 87 * @param {number} navigationStart |
| 58 this._request.removeEventListener(WebInspector.NetworkRequest.Events.Fin
ishedLoading, this._refresh, this); | 88 * @return {!Array.<!WebInspector.RequestTimeRange>} |
| 59 this._calculator.removeEventListener(WebInspector.NetworkTimeCalculator.
Events.BoundariesChanged, this._refresh, this); | 89 */ |
| 60 }, | 90 static calculateRequestTimeRanges(request, navigationStart) { |
| 61 | |
| 62 _refresh: function() | |
| 63 { | |
| 64 if (this._tableElement) | |
| 65 this._tableElement.remove(); | |
| 66 | |
| 67 this._tableElement = WebInspector.RequestTimingView.createTimingTable(th
is._request, this._calculator.minimumBoundary()); | |
| 68 this.element.appendChild(this._tableElement); | |
| 69 }, | |
| 70 | |
| 71 __proto__: WebInspector.VBox.prototype | |
| 72 }; | |
| 73 | |
| 74 /** @enum {string} */ | |
| 75 WebInspector.RequestTimeRangeNames = { | |
| 76 Push: "push", | |
| 77 Queueing: "queueing", | |
| 78 Blocking: "blocking", | |
| 79 Connecting: "connecting", | |
| 80 DNS: "dns", | |
| 81 Proxy: "proxy", | |
| 82 Receiving: "receiving", | |
| 83 ReceivingPush: "receiving-push", | |
| 84 Sending: "sending", | |
| 85 ServiceWorker: "serviceworker", | |
| 86 ServiceWorkerPreparation: "serviceworker-preparation", | |
| 87 SSL: "ssl", | |
| 88 Total: "total", | |
| 89 Waiting: "waiting" | |
| 90 }; | |
| 91 | |
| 92 WebInspector.RequestTimingView.ConnectionSetupRangeNames = new Set([ | |
| 93 WebInspector.RequestTimeRangeNames.Queueing, | |
| 94 WebInspector.RequestTimeRangeNames.Blocking, | |
| 95 WebInspector.RequestTimeRangeNames.Connecting, | |
| 96 WebInspector.RequestTimeRangeNames.DNS, | |
| 97 WebInspector.RequestTimeRangeNames.Proxy, | |
| 98 WebInspector.RequestTimeRangeNames.SSL | |
| 99 ]); | |
| 100 | |
| 101 /** @typedef {{name: !WebInspector.RequestTimeRangeNames, start: number, end: nu
mber}} */ | |
| 102 WebInspector.RequestTimeRange; | |
| 103 | |
| 104 /** | |
| 105 * @param {!WebInspector.RequestTimeRangeNames} name | |
| 106 * @return {string} | |
| 107 */ | |
| 108 WebInspector.RequestTimingView._timeRangeTitle = function(name) | |
| 109 { | |
| 110 switch (name) { | |
| 111 case WebInspector.RequestTimeRangeNames.Push: return WebInspector.UIString("
Receiving Push"); | |
| 112 case WebInspector.RequestTimeRangeNames.Queueing: return WebInspector.UIStri
ng("Queueing"); | |
| 113 case WebInspector.RequestTimeRangeNames.Blocking: return WebInspector.UIStri
ng("Stalled"); | |
| 114 case WebInspector.RequestTimeRangeNames.Connecting: return WebInspector.UISt
ring("Initial connection"); | |
| 115 case WebInspector.RequestTimeRangeNames.DNS: return WebInspector.UIString("D
NS Lookup"); | |
| 116 case WebInspector.RequestTimeRangeNames.Proxy: return WebInspector.UIString(
"Proxy negotiation"); | |
| 117 case WebInspector.RequestTimeRangeNames.ReceivingPush: return WebInspector.U
IString("Reading Push"); | |
| 118 case WebInspector.RequestTimeRangeNames.Receiving: return WebInspector.UIStr
ing("Content Download"); | |
| 119 case WebInspector.RequestTimeRangeNames.Sending: return WebInspector.UIStrin
g("Request sent"); | |
| 120 case WebInspector.RequestTimeRangeNames.ServiceWorker: return WebInspector.U
IString("Request to ServiceWorker"); | |
| 121 case WebInspector.RequestTimeRangeNames.ServiceWorkerPreparation: return Web
Inspector.UIString("ServiceWorker Preparation"); | |
| 122 case WebInspector.RequestTimeRangeNames.SSL: return WebInspector.UIString("S
SL"); | |
| 123 case WebInspector.RequestTimeRangeNames.Total: return WebInspector.UIString(
"Total"); | |
| 124 case WebInspector.RequestTimeRangeNames.Waiting: return WebInspector.UIStrin
g("Waiting (TTFB)"); | |
| 125 default: return WebInspector.UIString(name); | |
| 126 } | |
| 127 }; | |
| 128 | |
| 129 /** | |
| 130 * @param {!WebInspector.NetworkRequest} request | |
| 131 * @param {number} navigationStart | |
| 132 * @return {!Array.<!WebInspector.RequestTimeRange>} | |
| 133 */ | |
| 134 WebInspector.RequestTimingView.calculateRequestTimeRanges = function(request, na
vigationStart) | |
| 135 { | |
| 136 var result = []; | 91 var result = []; |
| 137 /** | 92 /** |
| 138 * @param {!WebInspector.RequestTimeRangeNames} name | 93 * @param {!WebInspector.RequestTimeRangeNames} name |
| 139 * @param {number} start | 94 * @param {number} start |
| 140 * @param {number} end | 95 * @param {number} end |
| 141 */ | 96 */ |
| 142 function addRange(name, start, end) | 97 function addRange(name, start, end) { |
| 143 { | 98 if (start < Number.MAX_VALUE && start <= end) |
| 144 if (start < Number.MAX_VALUE && start <= end) | 99 result.push({name: name, start: start, end: end}); |
| 145 result.push({name: name, start: start, end: end}); | |
| 146 } | 100 } |
| 147 | 101 |
| 148 /** | 102 /** |
| 149 * @param {!Array.<number>} numbers | 103 * @param {!Array.<number>} numbers |
| 150 * @return {number|undefined} | 104 * @return {number|undefined} |
| 151 */ | 105 */ |
| 152 function firstPositive(numbers) | 106 function firstPositive(numbers) { |
| 153 { | 107 for (var i = 0; i < numbers.length; ++i) { |
| 154 for (var i = 0; i < numbers.length; ++i) { | 108 if (numbers[i] > 0) |
| 155 if (numbers[i] > 0) | 109 return numbers[i]; |
| 156 return numbers[i]; | 110 } |
| 157 } | 111 return undefined; |
| 158 return undefined; | |
| 159 } | 112 } |
| 160 | 113 |
| 161 /** | 114 /** |
| 162 * @param {!WebInspector.RequestTimeRangeNames} name | 115 * @param {!WebInspector.RequestTimeRangeNames} name |
| 163 * @param {number} start | 116 * @param {number} start |
| 164 * @param {number} end | 117 * @param {number} end |
| 165 */ | 118 */ |
| 166 function addOffsetRange(name, start, end) | 119 function addOffsetRange(name, start, end) { |
| 167 { | 120 if (start >= 0 && end >= 0) |
| 168 if (start >= 0 && end >= 0) | 121 addRange(name, startTime + (start / 1000), startTime + (end / 1000)); |
| 169 addRange(name, startTime + (start / 1000), startTime + (end / 1000))
; | |
| 170 } | 122 } |
| 171 | 123 |
| 172 var timing = request.timing; | 124 var timing = request.timing; |
| 173 if (!timing) { | 125 if (!timing) { |
| 174 var start = request.issueTime() !== -1 ? request.issueTime() : request.s
tartTime !== -1 ? request.startTime : 0; | 126 var start = request.issueTime() !== -1 ? request.issueTime() : request.sta
rtTime !== -1 ? request.startTime : 0; |
| 175 var middle = (request.responseReceivedTime === -1) ? Number.MAX_VALUE :
request.responseReceivedTime; | 127 var middle = (request.responseReceivedTime === -1) ? Number.MAX_VALUE : re
quest.responseReceivedTime; |
| 176 var end = (request.endTime === -1) ? Number.MAX_VALUE : request.endTime; | 128 var end = (request.endTime === -1) ? Number.MAX_VALUE : request.endTime; |
| 177 addRange(WebInspector.RequestTimeRangeNames.Total, start, end); | 129 addRange(WebInspector.RequestTimeRangeNames.Total, start, end); |
| 178 addRange(WebInspector.RequestTimeRangeNames.Blocking, start, middle); | 130 addRange(WebInspector.RequestTimeRangeNames.Blocking, start, middle); |
| 179 addRange(WebInspector.RequestTimeRangeNames.Receiving, middle, end); | 131 addRange(WebInspector.RequestTimeRangeNames.Receiving, middle, end); |
| 180 return result; | 132 return result; |
| 181 } | 133 } |
| 182 | 134 |
| 183 var issueTime = request.issueTime(); | 135 var issueTime = request.issueTime(); |
| 184 var startTime = timing.requestTime; | 136 var startTime = timing.requestTime; |
| 185 var endTime = firstPositive([request.endTime, request.responseReceivedTime])
|| startTime; | 137 var endTime = firstPositive([request.endTime, request.responseReceivedTime])
|| startTime; |
| 186 | 138 |
| 187 addRange(WebInspector.RequestTimeRangeNames.Total, issueTime < startTime ? i
ssueTime : startTime, endTime); | 139 addRange(WebInspector.RequestTimeRangeNames.Total, issueTime < startTime ? i
ssueTime : startTime, endTime); |
| 188 if (timing.pushStart) { | 140 if (timing.pushStart) { |
| 189 var pushEnd = timing.pushEnd || endTime; | 141 var pushEnd = timing.pushEnd || endTime; |
| 190 // Only show the part of push that happened after the navigation/reload. | 142 // Only show the part of push that happened after the navigation/reload. |
| 191 // Pushes that happened on the same connection before we started main re
quest will not be shown. | 143 // Pushes that happened on the same connection before we started main requ
est will not be shown. |
| 192 if (pushEnd > navigationStart) | 144 if (pushEnd > navigationStart) |
| 193 addRange(WebInspector.RequestTimeRangeNames.Push, Math.max(timing.pu
shStart, navigationStart), pushEnd); | 145 addRange(WebInspector.RequestTimeRangeNames.Push, Math.max(timing.pushSt
art, navigationStart), pushEnd); |
| 194 } | 146 } |
| 195 if (issueTime < startTime) | 147 if (issueTime < startTime) |
| 196 addRange(WebInspector.RequestTimeRangeNames.Queueing, issueTime, startTi
me); | 148 addRange(WebInspector.RequestTimeRangeNames.Queueing, issueTime, startTime
); |
| 197 | 149 |
| 198 if (request.fetchedViaServiceWorker) { | 150 if (request.fetchedViaServiceWorker) { |
| 199 addOffsetRange(WebInspector.RequestTimeRangeNames.Blocking, 0, timing.wo
rkerStart); | 151 addOffsetRange(WebInspector.RequestTimeRangeNames.Blocking, 0, timing.work
erStart); |
| 200 addOffsetRange(WebInspector.RequestTimeRangeNames.ServiceWorkerPreparati
on, timing.workerStart, timing.workerReady); | 152 addOffsetRange( |
| 201 addOffsetRange(WebInspector.RequestTimeRangeNames.ServiceWorker, timing.
workerReady, timing.sendEnd); | 153 WebInspector.RequestTimeRangeNames.ServiceWorkerPreparation, timing.wo
rkerStart, timing.workerReady); |
| 202 addOffsetRange(WebInspector.RequestTimeRangeNames.Waiting, timing.sendEn
d, timing.receiveHeadersEnd); | 154 addOffsetRange(WebInspector.RequestTimeRangeNames.ServiceWorker, timing.wo
rkerReady, timing.sendEnd); |
| 155 addOffsetRange(WebInspector.RequestTimeRangeNames.Waiting, timing.sendEnd,
timing.receiveHeadersEnd); |
| 203 } else if (!timing.pushStart) { | 156 } else if (!timing.pushStart) { |
| 204 var blocking = firstPositive([timing.dnsStart, timing.connectStart, timi
ng.sendStart]) || 0; | 157 var blocking = firstPositive([timing.dnsStart, timing.connectStart, timing
.sendStart]) || 0; |
| 205 addOffsetRange(WebInspector.RequestTimeRangeNames.Blocking, 0, blocking)
; | 158 addOffsetRange(WebInspector.RequestTimeRangeNames.Blocking, 0, blocking); |
| 206 addOffsetRange(WebInspector.RequestTimeRangeNames.Proxy, timing.proxySta
rt, timing.proxyEnd); | 159 addOffsetRange(WebInspector.RequestTimeRangeNames.Proxy, timing.proxyStart
, timing.proxyEnd); |
| 207 addOffsetRange(WebInspector.RequestTimeRangeNames.DNS, timing.dnsStart,
timing.dnsEnd); | 160 addOffsetRange(WebInspector.RequestTimeRangeNames.DNS, timing.dnsStart, ti
ming.dnsEnd); |
| 208 addOffsetRange(WebInspector.RequestTimeRangeNames.Connecting, timing.con
nectStart, timing.connectEnd); | 161 addOffsetRange(WebInspector.RequestTimeRangeNames.Connecting, timing.conne
ctStart, timing.connectEnd); |
| 209 addOffsetRange(WebInspector.RequestTimeRangeNames.SSL, timing.sslStart,
timing.sslEnd); | 162 addOffsetRange(WebInspector.RequestTimeRangeNames.SSL, timing.sslStart, ti
ming.sslEnd); |
| 210 addOffsetRange(WebInspector.RequestTimeRangeNames.Sending, timing.sendSt
art, timing.sendEnd); | 163 addOffsetRange(WebInspector.RequestTimeRangeNames.Sending, timing.sendStar
t, timing.sendEnd); |
| 211 addOffsetRange(WebInspector.RequestTimeRangeNames.Waiting, timing.sendEn
d, timing.receiveHeadersEnd); | 164 addOffsetRange(WebInspector.RequestTimeRangeNames.Waiting, timing.sendEnd,
timing.receiveHeadersEnd); |
| 212 } | 165 } |
| 213 | 166 |
| 214 if (request.endTime !== -1) | 167 if (request.endTime !== -1) |
| 215 addRange(timing.pushStart ? WebInspector.RequestTimeRangeNames.Receiving
Push : WebInspector.RequestTimeRangeNames.Receiving, request.responseReceivedTim
e, endTime); | 168 addRange( |
| 169 timing.pushStart ? WebInspector.RequestTimeRangeNames.ReceivingPush : |
| 170 WebInspector.RequestTimeRangeNames.Receiving, |
| 171 request.responseReceivedTime, endTime); |
| 216 | 172 |
| 217 return result; | 173 return result; |
| 218 }; | 174 } |
| 219 | 175 |
| 220 /** | 176 /** |
| 221 * @param {!WebInspector.NetworkRequest} request | 177 * @param {!WebInspector.NetworkRequest} request |
| 222 * @param {number} navigationStart | 178 * @param {number} navigationStart |
| 223 * @return {!Element} | 179 * @return {!Element} |
| 224 */ | 180 */ |
| 225 WebInspector.RequestTimingView.createTimingTable = function(request, navigationS
tart) | 181 static createTimingTable(request, navigationStart) { |
| 226 { | 182 var tableElement = createElementWithClass('table', 'network-timing-table'); |
| 227 var tableElement = createElementWithClass("table", "network-timing-table"); | 183 var colgroup = tableElement.createChild('colgroup'); |
| 228 var colgroup = tableElement.createChild("colgroup"); | 184 colgroup.createChild('col', 'labels'); |
| 229 colgroup.createChild("col", "labels"); | 185 colgroup.createChild('col', 'bars'); |
| 230 colgroup.createChild("col", "bars"); | 186 colgroup.createChild('col', 'duration'); |
| 231 colgroup.createChild("col", "duration"); | |
| 232 | 187 |
| 233 var timeRanges = WebInspector.RequestTimingView.calculateRequestTimeRanges(r
equest, navigationStart); | 188 var timeRanges = WebInspector.RequestTimingView.calculateRequestTimeRanges(r
equest, navigationStart); |
| 234 var startTime = timeRanges.map(r => r.start).reduce((a, b) => Math.min(a, b)
); | 189 var startTime = timeRanges.map(r => r.start).reduce((a, b) => Math.min(a, b)
); |
| 235 var endTime = timeRanges.map(r => r.end).reduce((a, b) => Math.max(a, b)); | 190 var endTime = timeRanges.map(r => r.end).reduce((a, b) => Math.max(a, b)); |
| 236 var scale = 100 / (endTime - startTime); | 191 var scale = 100 / (endTime - startTime); |
| 237 | 192 |
| 238 var connectionHeader; | 193 var connectionHeader; |
| 239 var dataHeader; | 194 var dataHeader; |
| 240 var totalDuration = 0; | 195 var totalDuration = 0; |
| 241 | 196 |
| 242 for (var i = 0; i < timeRanges.length; ++i) { | 197 for (var i = 0; i < timeRanges.length; ++i) { |
| 243 var range = timeRanges[i]; | 198 var range = timeRanges[i]; |
| 244 var rangeName = range.name; | 199 var rangeName = range.name; |
| 245 if (rangeName === WebInspector.RequestTimeRangeNames.Total) { | 200 if (rangeName === WebInspector.RequestTimeRangeNames.Total) { |
| 246 totalDuration = range.end - range.start; | 201 totalDuration = range.end - range.start; |
| 247 continue; | 202 continue; |
| 248 } | 203 } |
| 249 if (rangeName === WebInspector.RequestTimeRangeNames.Push) { | 204 if (rangeName === WebInspector.RequestTimeRangeNames.Push) { |
| 250 createHeader(WebInspector.UIString("Server Push")); | 205 createHeader(WebInspector.UIString('Server Push')); |
| 251 } else if (WebInspector.RequestTimingView.ConnectionSetupRangeNames.has(
rangeName)) { | 206 } else if (WebInspector.RequestTimingView.ConnectionSetupRangeNames.has(ra
ngeName)) { |
| 252 if (!connectionHeader) | 207 if (!connectionHeader) |
| 253 connectionHeader = createHeader(WebInspector.UIString("Connectio
n Setup")); | 208 connectionHeader = createHeader(WebInspector.UIString('Connection Setu
p')); |
| 254 } else { | 209 } else { |
| 255 if (!dataHeader) | 210 if (!dataHeader) |
| 256 dataHeader = createHeader(WebInspector.UIString("Request/Respons
e")); | 211 dataHeader = createHeader(WebInspector.UIString('Request/Response')); |
| 257 } | 212 } |
| 258 | 213 |
| 259 var left = (scale * (range.start - startTime)); | 214 var left = (scale * (range.start - startTime)); |
| 260 var right = (scale * (endTime - range.end)); | 215 var right = (scale * (endTime - range.end)); |
| 261 var duration = range.end - range.start; | 216 var duration = range.end - range.start; |
| 262 | 217 |
| 263 var tr = tableElement.createChild("tr"); | 218 var tr = tableElement.createChild('tr'); |
| 264 tr.createChild("td").createTextChild(WebInspector.RequestTimingView._tim
eRangeTitle(rangeName)); | 219 tr.createChild('td').createTextChild(WebInspector.RequestTimingView._timeR
angeTitle(rangeName)); |
| 265 | 220 |
| 266 var row = tr.createChild("td").createChild("div", "network-timing-row"); | 221 var row = tr.createChild('td').createChild('div', 'network-timing-row'); |
| 267 var bar = row.createChild("span", "network-timing-bar " + rangeName); | 222 var bar = row.createChild('span', 'network-timing-bar ' + rangeName); |
| 268 bar.style.left = left + "%"; | 223 bar.style.left = left + '%'; |
| 269 bar.style.right = right + "%"; | 224 bar.style.right = right + '%'; |
| 270 bar.textContent = "\u200B"; // Important for 0-time items to have 0 widt
h. | 225 bar.textContent = '\u200B'; // Important for 0-time items to have 0 width
. |
| 271 var label = tr.createChild("td").createChild("div", "network-timing-bar-
title"); | 226 var label = tr.createChild('td').createChild('div', 'network-timing-bar-ti
tle'); |
| 272 label.textContent = Number.secondsToString(duration, true); | 227 label.textContent = Number.secondsToString(duration, true); |
| 273 } | 228 } |
| 274 | 229 |
| 275 if (!request.finished) { | 230 if (!request.finished) { |
| 276 var cell = tableElement.createChild("tr").createChild("td", "caution"); | 231 var cell = tableElement.createChild('tr').createChild('td', 'caution'); |
| 277 cell.colSpan = 3; | 232 cell.colSpan = 3; |
| 278 cell.createTextChild(WebInspector.UIString("CAUTION: request is not fini
shed yet!")); | 233 cell.createTextChild(WebInspector.UIString('CAUTION: request is not finish
ed yet!')); |
| 279 } | 234 } |
| 280 | 235 |
| 281 var footer = tableElement.createChild("tr", "network-timing-footer"); | 236 var footer = tableElement.createChild('tr', 'network-timing-footer'); |
| 282 var note = footer.createChild("td"); | 237 var note = footer.createChild('td'); |
| 283 note.colSpan = 2; | 238 note.colSpan = 2; |
| 284 note.appendChild(WebInspector.linkifyDocumentationURLAsNode("profile/network
-performance/resource-loading#view-network-timing-details-for-a-specific-resourc
e", WebInspector.UIString("Explanation"))); | 239 note.appendChild(WebInspector.linkifyDocumentationURLAsNode( |
| 285 footer.createChild("td").createTextChild(Number.secondsToString(totalDuratio
n, true)); | 240 'profile/network-performance/resource-loading#view-network-timing-detail
s-for-a-specific-resource', |
| 241 WebInspector.UIString('Explanation'))); |
| 242 footer.createChild('td').createTextChild(Number.secondsToString(totalDuratio
n, true)); |
| 286 | 243 |
| 287 var serverTimings = request.serverTimings; | 244 var serverTimings = request.serverTimings; |
| 288 if (!serverTimings) | 245 if (!serverTimings) |
| 289 return tableElement; | 246 return tableElement; |
| 290 | 247 |
| 291 var lastTimingRightEdge = right === undefined ? 100 : right; | 248 var lastTimingRightEdge = right === undefined ? 100 : right; |
| 292 | 249 |
| 293 var breakElement = tableElement.createChild("tr", "network-timing-table-head
er").createChild("td"); | 250 var breakElement = tableElement.createChild('tr', 'network-timing-table-head
er').createChild('td'); |
| 294 breakElement.colSpan = 3; | 251 breakElement.colSpan = 3; |
| 295 breakElement.createChild("hr", "break"); | 252 breakElement.createChild('hr', 'break'); |
| 296 | 253 |
| 297 var serverHeader = tableElement.createChild("tr", "network-timing-table-head
er"); | 254 var serverHeader = tableElement.createChild('tr', 'network-timing-table-head
er'); |
| 298 serverHeader.createChild("td").createTextChild(WebInspector.UIString("Server
Timing")); | 255 serverHeader.createChild('td').createTextChild(WebInspector.UIString('Server
Timing')); |
| 299 serverHeader.createChild("td"); | 256 serverHeader.createChild('td'); |
| 300 serverHeader.createChild("td").createTextChild(WebInspector.UIString("TIME")
); | 257 serverHeader.createChild('td').createTextChild(WebInspector.UIString('TIME')
); |
| 301 | 258 |
| 302 serverTimings.filter(item => item.metric.toLowerCase() !== "total").forEach(
item => addTiming(item, lastTimingRightEdge)); | 259 serverTimings.filter(item => item.metric.toLowerCase() !== 'total') |
| 303 serverTimings.filter(item => item.metric.toLowerCase() === "total").forEach(
item => addTiming(item, lastTimingRightEdge)); | 260 .forEach(item => addTiming(item, lastTimingRightEdge)); |
| 261 serverTimings.filter(item => item.metric.toLowerCase() === 'total') |
| 262 .forEach(item => addTiming(item, lastTimingRightEdge)); |
| 304 | 263 |
| 305 return tableElement; | 264 return tableElement; |
| 306 | 265 |
| 307 | |
| 308 /** | 266 /** |
| 309 * @param {!WebInspector.ServerTiming} serverTiming | 267 * @param {!WebInspector.ServerTiming} serverTiming |
| 310 * @param {number} right | 268 * @param {number} right |
| 311 */ | 269 */ |
| 312 function addTiming(serverTiming, right) | 270 function addTiming(serverTiming, right) { |
| 313 { | 271 var colorGenerator = |
| 314 var colorGenerator = new WebInspector.FlameChart.ColorGenerator( | 272 new WebInspector.FlameChart.ColorGenerator({min: 0, max: 360, count: 3
6}, {min: 50, max: 80}, 80); |
| 315 { min: 0, max: 360, count:36 }, | 273 var isTotal = serverTiming.metric.toLowerCase() === 'total'; |
| 316 { min: 50, max: 80 }, | 274 var tr = tableElement.createChild('tr', isTotal ? 'network-timing-footer'
: ''); |
| 317 80 | 275 var metric = tr.createChild('td', 'network-timing-metric'); |
| 318 ); | 276 metric.createTextChild(serverTiming.description || serverTiming.metric); |
| 319 var isTotal = serverTiming.metric.toLowerCase() === "total"; | 277 var row = tr.createChild('td').createChild('div', 'network-timing-row'); |
| 320 var tr = tableElement.createChild("tr", isTotal ? "network-timing-footer
" : ""); | 278 var left = scale * (endTime - startTime - serverTiming.value); |
| 321 var metric = tr.createChild("td", "network-timing-metric"); | 279 if (serverTiming.value && left >= 0) { // don't chart values too big or t
oo small |
| 322 metric.createTextChild(serverTiming.description || serverTiming.metric); | 280 var bar = row.createChild('span', 'network-timing-bar server-timing'); |
| 323 var row = tr.createChild("td").createChild("div", "network-timing-row"); | 281 bar.style.left = left + '%'; |
| 324 var left = scale * (endTime - startTime - serverTiming.value); | 282 bar.style.right = right + '%'; |
| 325 if (serverTiming.value && left >= 0) { // don't chart values too big or
too small | 283 bar.textContent = '\u200B'; // Important for 0-time items to have 0 wid
th. |
| 326 var bar = row.createChild("span", "network-timing-bar server-timing"
); | 284 if (!isTotal) |
| 327 bar.style.left = left + "%"; | 285 bar.style.backgroundColor = colorGenerator.colorForID(serverTiming.met
ric); |
| 328 bar.style.right = right + "%"; | 286 } |
| 329 bar.textContent = "\u200B"; // Important for 0-time items to have 0
width. | 287 var label = tr.createChild('td').createChild('div', 'network-timing-bar-ti
tle'); |
| 330 if (!isTotal) | 288 if (typeof serverTiming.value === 'number') // a metric timing value is o
ptional |
| 331 bar.style.backgroundColor = colorGenerator.colorForID(serverTimi
ng.metric); | 289 label.textContent = Number.secondsToString(serverTiming.value, true); |
| 332 } | |
| 333 var label = tr.createChild("td").createChild("div", "network-timing-bar-
title"); | |
| 334 if (typeof serverTiming.value === "number") // a metric timing value is
optional | |
| 335 label.textContent = Number.secondsToString(serverTiming.value, true)
; | |
| 336 } | 290 } |
| 337 | 291 |
| 338 /** | 292 /** |
| 339 * param {string} title | 293 * param {string} title |
| 340 */ | 294 */ |
| 341 function createHeader(title) | 295 function createHeader(title) { |
| 342 { | 296 var dataHeader = tableElement.createChild('tr', 'network-timing-table-head
er'); |
| 343 var dataHeader = tableElement.createChild("tr", "network-timing-table-he
ader"); | 297 dataHeader.createChild('td').createTextChild(title); |
| 344 dataHeader.createChild("td").createTextChild(title); | 298 dataHeader.createChild('td').createTextChild(''); |
| 345 dataHeader.createChild("td").createTextChild(""); | 299 dataHeader.createChild('td').createTextChild(WebInspector.UIString('TIME')
); |
| 346 dataHeader.createChild("td").createTextChild(WebInspector.UIString("TIME
")); | 300 return dataHeader; |
| 347 return dataHeader; | |
| 348 } | 301 } |
| 302 } |
| 303 |
| 304 /** |
| 305 * @override |
| 306 */ |
| 307 wasShown() { |
| 308 this._request.addEventListener(WebInspector.NetworkRequest.Events.TimingChan
ged, this._refresh, this); |
| 309 this._request.addEventListener(WebInspector.NetworkRequest.Events.FinishedLo
ading, this._refresh, this); |
| 310 this._calculator.addEventListener(WebInspector.NetworkTimeCalculator.Events.
BoundariesChanged, this._refresh, this); |
| 311 this._refresh(); |
| 312 } |
| 313 |
| 314 /** |
| 315 * @override |
| 316 */ |
| 317 willHide() { |
| 318 this._request.removeEventListener(WebInspector.NetworkRequest.Events.TimingC
hanged, this._refresh, this); |
| 319 this._request.removeEventListener(WebInspector.NetworkRequest.Events.Finishe
dLoading, this._refresh, this); |
| 320 this._calculator.removeEventListener( |
| 321 WebInspector.NetworkTimeCalculator.Events.BoundariesChanged, this._refre
sh, this); |
| 322 } |
| 323 |
| 324 _refresh() { |
| 325 if (this._tableElement) |
| 326 this._tableElement.remove(); |
| 327 |
| 328 this._tableElement = |
| 329 WebInspector.RequestTimingView.createTimingTable(this._request, this._ca
lculator.minimumBoundary()); |
| 330 this.element.appendChild(this._tableElement); |
| 331 } |
| 349 }; | 332 }; |
| 333 |
| 334 /** @enum {string} */ |
| 335 WebInspector.RequestTimeRangeNames = { |
| 336 Push: 'push', |
| 337 Queueing: 'queueing', |
| 338 Blocking: 'blocking', |
| 339 Connecting: 'connecting', |
| 340 DNS: 'dns', |
| 341 Proxy: 'proxy', |
| 342 Receiving: 'receiving', |
| 343 ReceivingPush: 'receiving-push', |
| 344 Sending: 'sending', |
| 345 ServiceWorker: 'serviceworker', |
| 346 ServiceWorkerPreparation: 'serviceworker-preparation', |
| 347 SSL: 'ssl', |
| 348 Total: 'total', |
| 349 Waiting: 'waiting' |
| 350 }; |
| 351 |
| 352 WebInspector.RequestTimingView.ConnectionSetupRangeNames = new Set([ |
| 353 WebInspector.RequestTimeRangeNames.Queueing, WebInspector.RequestTimeRangeName
s.Blocking, |
| 354 WebInspector.RequestTimeRangeNames.Connecting, WebInspector.RequestTimeRangeNa
mes.DNS, |
| 355 WebInspector.RequestTimeRangeNames.Proxy, WebInspector.RequestTimeRangeNames.S
SL |
| 356 ]); |
| 357 |
| 358 /** @typedef {{name: !WebInspector.RequestTimeRangeNames, start: number, end: nu
mber}} */ |
| 359 WebInspector.RequestTimeRange; |
| 360 |
| 361 |
| OLD | NEW |