Home | History | Annotate | Download | only in front-end
      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