1 /* 2 * Copyright (C) 2010 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 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. 29 */ 30 31 WebInspector.ResourceTimingView = function(resource) 32 { 33 WebInspector.View.call(this); 34 this.element.addStyleClass("resource-timing-view"); 35 36 this._resource = resource; 37 38 resource.addEventListener("timing changed", this._refresh, this); 39 } 40 41 WebInspector.ResourceTimingView.prototype = { 42 show: function(parentElement) 43 { 44 if (!this._resource.timing) { 45 if (!this._emptyMsgElement) { 46 this._emptyMsgElement = document.createElement("div"); 47 this._emptyMsgElement.className = "storage-empty-view"; 48 this._emptyMsgElement.textContent = WebInspector.UIString("This request has no detailed timing info."); 49 this.element.appendChild(this._emptyMsgElement); 50 } 51 WebInspector.View.prototype.show.call(this, parentElement); 52 return; 53 } 54 55 if (this._emptyMsgElement) 56 this._emptyMsgElement.parentElement.removeChild(this._emptyMsgElement); 57 58 this._refresh(); 59 WebInspector.View.prototype.show.call(this, parentElement); 60 }, 61 62 _refresh: function() 63 { 64 if (this._tableElement) 65 this._tableElement.parentElement.removeChild(this._tableElement); 66 67 this._tableElement = WebInspector.ResourceTimingView.createTimingTable(this._resource); 68 this.element.appendChild(this._tableElement); 69 } 70 } 71 72 WebInspector.ResourceTimingView.createTimingTable = function(resource) 73 { 74 var tableElement = document.createElement("table"); 75 var rows = []; 76 77 function addRow(title, className, start, end, color) 78 { 79 var row = {}; 80 row.title = title; 81 row.className = className; 82 row.start = start; 83 row.end = end; 84 rows.push(row); 85 } 86 87 if (resource.timing.proxyStart !== -1) 88 addRow(WebInspector.UIString("Proxy"), "proxy", resource.timing.proxyStart, resource.timing.proxyEnd); 89 90 if (resource.timing.dnsStart !== -1) 91 addRow(WebInspector.UIString("DNS Lookup"), "dns", resource.timing.dnsStart, resource.timing.dnsEnd); 92 93 if (resource.timing.connectStart !== -1) { 94 if (resource.connectionReused) 95 addRow(WebInspector.UIString("Blocking"), "connecting", resource.timing.connectStart, resource.timing.connectEnd); 96 else { 97 var connectStart = resource.timing.connectStart; 98 // Connection includes DNS, subtract it here. 99 if (resource.timing.dnsStart !== -1) 100 connectStart += resource.timing.dnsEnd - resource.timing.dnsStart; 101 addRow(WebInspector.UIString("Connecting"), "connecting", connectStart, resource.timing.connectEnd); 102 } 103 } 104 105 if (resource.timing.sslStart !== -1) 106 addRow(WebInspector.UIString("SSL"), "ssl", resource.timing.sslStart, resource.timing.sslEnd); 107 108 var sendStart = resource.timing.sendStart; 109 if (resource.timing.sslStart !== -1) 110 sendStart += resource.timing.sslEnd - resource.timing.sslStart; 111 112 addRow(WebInspector.UIString("Sending"), "sending", resource.timing.sendStart, resource.timing.sendEnd); 113 addRow(WebInspector.UIString("Waiting"), "waiting", resource.timing.sendEnd, resource.timing.receiveHeadersEnd); 114 addRow(WebInspector.UIString("Receiving"), "receiving", (resource.responseReceivedTime - resource.timing.requestTime) * 1000, (resource.endTime - resource.timing.requestTime) * 1000); 115 116 const chartWidth = 200; 117 var total = (resource.endTime - resource.timing.requestTime) * 1000; 118 var scale = chartWidth / total; 119 120 for (var i = 0; i < rows.length; ++i) { 121 var tr = document.createElement("tr"); 122 tableElement.appendChild(tr); 123 124 var td = document.createElement("td"); 125 td.textContent = rows[i].title; 126 tr.appendChild(td); 127 128 td = document.createElement("td"); 129 td.width = chartWidth + "px"; 130 131 var row = document.createElement("div"); 132 row.className = "network-timing-row"; 133 td.appendChild(row); 134 135 var bar = document.createElement("span"); 136 bar.className = "network-timing-bar " + rows[i].className; 137 bar.style.left = scale * rows[i].start + "px"; 138 bar.style.right = scale * (total - rows[i].end) + "px"; 139 bar.style.backgroundColor = rows[i].color; 140 bar.textContent = "\u200B"; // Important for 0-time items to have 0 width. 141 row.appendChild(bar); 142 143 var title = document.createElement("span"); 144 title.className = "network-timing-bar-title"; 145 if (total - rows[i].end < rows[i].start) 146 title.style.right = (scale * (total - rows[i].end) + 3) + "px"; 147 else 148 title.style.left = (scale * rows[i].start + 3) + "px"; 149 title.textContent = Number.millisToString(rows[i].end - rows[i].start); 150 row.appendChild(title); 151 152 tr.appendChild(td); 153 } 154 return tableElement; 155 } 156 157 WebInspector.ResourceTimingView.prototype.__proto__ = WebInspector.View.prototype; 158