Web Inspector: Network Table - Redesign the waterfall popover showing timing data
authorjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Dec 2017 00:56:31 +0000 (00:56 +0000)
committerjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Dec 2017 00:56:31 +0000 (00:56 +0000)
https://bugs.webkit.org/show_bug.cgi?id=180996
<rdar://problem/34072542>

Reviewed by Matt Baker.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Main.html:
New strings and files.

* UserInterface/Views/NetworkTableContentView.js:
(WI.NetworkTableContentView.prototype._waterfallPopoverContentForResource):
(WI.NetworkTableContentView.prototype._handleMousedownWaterfall):
Use the ResourceTimingBreakdownView with a fixed width size.

* UserInterface/Views/ResourceTimingContentView.css: Removed.
* UserInterface/Views/ResourceTimingContentView.js:
(WI.ResourceTimingContentView.prototype.initialLayout):
(WI.ResourceTimingContentView.prototype._refreshTimingSection):
(WI.ResourceTimingContentView.prototype._refreshTimingSection.createBlock): Deleted.
(WI.ResourceTimingContentView.prototype._refreshTimingSection.createTimeLabel): Deleted.
(WI.ResourceTimingContentView.prototype._refreshTimingSection.createRow): Deleted.
Use the ResourceTimingBreakdownView with a flexible size.
Also changed the loading indicator and empty message to match
normal ContentView loading indicator and message only UI.

* UserInterface/Views/ResourceTimingBreakdownView.css:
(.waterfall-popover .resource-timing-breakdown):
(.resource-timing-breakdown > table > tr > td.label):
(.resource-timing-breakdown > table > tr > td.graph):
(.resource-timing-breakdown > table > tr > td.time):
(.resource-timing-breakdown > table > tr.empty):
(.resource-timing-breakdown > table > tr.header:not(.total-row) > td):
(.resource-timing-breakdown > table hr):
(.resource-timing-breakdown .waterfall .block):
(.resource-timing-breakdown): Deleted.
(.resource-timing-breakdown > .waterfall): Deleted.
(.resource-timing-breakdown > .waterfall .block): Deleted.
(.resource-timing-breakdown ul): Deleted.
(.resource-timing-breakdown ul > li): Deleted.
(.resource-timing-breakdown ul > li > .row-label): Deleted.
(body[dir=ltr] .resource-timing-breakdown ul > li > .row-label): Deleted.
(body[dir=rtl] .resource-timing-breakdown ul > li > .row-label): Deleted.
(.resource-timing-breakdown ul > li > .section-label): Deleted.
(.resource-timing-breakdown ul > li > .time-label): Deleted.
(.resource-timing-breakdown .time-section): Deleted.
(.resource-timing-breakdown ul > li > .time-section > .label): Deleted.
(.resource-timing-breakdown ul > li.total .block): Deleted.
(.resource-timing-breakdown ul > li.total .time-label): Deleted.
* UserInterface/Views/ResourceTimingBreakdownView.js:
(WI.ResourceTimingBreakdownView):
(WI.ResourceTimingBreakdownView.prototype._appendEmptyRow):
(WI.ResourceTimingBreakdownView.prototype._appendHeaderRow):
(WI.ResourceTimingBreakdownView.prototype._appendRow):
(WI.ResourceTimingBreakdownView.prototype.initialLayout):
(WI.ResourceTimingBreakdownView.prototype.initialLayout.createBlock): Deleted.
(WI.ResourceTimingBreakdownView.prototype.initialLayout.createSectionLabel): Deleted.
(WI.ResourceTimingBreakdownView.prototype.initialLayout.createTimeLabel): Deleted.
(WI.ResourceTimingBreakdownView.prototype.initialLayout.createTimeSection): Deleted.
(WI.ResourceTimingBreakdownView.prototype.initialLayout.createRow): Deleted.
(WI.ResourceTimingBreakdownView.prototype.initialLayout.emptyRow): Deleted.
(WI.ResourceTimingBreakdownView.prototype.initialLayout.appendGraphRow): Deleted.
(WI.ResourceTimingBreakdownView.prototype.initialLayout.appendEmptyRow): Deleted.
(WI.ResourceTimingBreakdownView.prototype.initialLayout.getCurrentSectionMetrics): Deleted.
Redesign the breakdown view.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@226158 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js
Source/WebInspectorUI/UserInterface/Views/ResourceTimingBreakdownView.css
Source/WebInspectorUI/UserInterface/Views/ResourceTimingBreakdownView.js
Source/WebInspectorUI/UserInterface/Views/ResourceTimingContentView.css [deleted file]
Source/WebInspectorUI/UserInterface/Views/ResourceTimingContentView.js

index 1ad3575..8e8949a 100644 (file)
@@ -1,3 +1,71 @@
+2017-12-19  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Network Table - Redesign the waterfall popover showing timing data
+        https://bugs.webkit.org/show_bug.cgi?id=180996
+        <rdar://problem/34072542>
+
+        Reviewed by Matt Baker.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Main.html:
+        New strings and files.
+
+        * UserInterface/Views/NetworkTableContentView.js:
+        (WI.NetworkTableContentView.prototype._waterfallPopoverContentForResource):
+        (WI.NetworkTableContentView.prototype._handleMousedownWaterfall):
+        Use the ResourceTimingBreakdownView with a fixed width size.
+
+        * UserInterface/Views/ResourceTimingContentView.css: Removed.
+        * UserInterface/Views/ResourceTimingContentView.js:
+        (WI.ResourceTimingContentView.prototype.initialLayout):
+        (WI.ResourceTimingContentView.prototype._refreshTimingSection):
+        (WI.ResourceTimingContentView.prototype._refreshTimingSection.createBlock): Deleted.
+        (WI.ResourceTimingContentView.prototype._refreshTimingSection.createTimeLabel): Deleted.
+        (WI.ResourceTimingContentView.prototype._refreshTimingSection.createRow): Deleted.
+        Use the ResourceTimingBreakdownView with a flexible size.
+        Also changed the loading indicator and empty message to match
+        normal ContentView loading indicator and message only UI.
+
+        * UserInterface/Views/ResourceTimingBreakdownView.css:
+        (.waterfall-popover .resource-timing-breakdown):
+        (.resource-timing-breakdown > table > tr > td.label):
+        (.resource-timing-breakdown > table > tr > td.graph):
+        (.resource-timing-breakdown > table > tr > td.time):
+        (.resource-timing-breakdown > table > tr.empty):
+        (.resource-timing-breakdown > table > tr.header:not(.total-row) > td):
+        (.resource-timing-breakdown > table hr):
+        (.resource-timing-breakdown .waterfall .block):
+        (.resource-timing-breakdown): Deleted.
+        (.resource-timing-breakdown > .waterfall): Deleted.
+        (.resource-timing-breakdown > .waterfall .block): Deleted.
+        (.resource-timing-breakdown ul): Deleted.
+        (.resource-timing-breakdown ul > li): Deleted.
+        (.resource-timing-breakdown ul > li > .row-label): Deleted.
+        (body[dir=ltr] .resource-timing-breakdown ul > li > .row-label): Deleted.
+        (body[dir=rtl] .resource-timing-breakdown ul > li > .row-label): Deleted.
+        (.resource-timing-breakdown ul > li > .section-label): Deleted.
+        (.resource-timing-breakdown ul > li > .time-label): Deleted.
+        (.resource-timing-breakdown .time-section): Deleted.
+        (.resource-timing-breakdown ul > li > .time-section > .label): Deleted.
+        (.resource-timing-breakdown ul > li.total .block): Deleted.
+        (.resource-timing-breakdown ul > li.total .time-label): Deleted.
+        * UserInterface/Views/ResourceTimingBreakdownView.js:
+        (WI.ResourceTimingBreakdownView):
+        (WI.ResourceTimingBreakdownView.prototype._appendEmptyRow):
+        (WI.ResourceTimingBreakdownView.prototype._appendHeaderRow):
+        (WI.ResourceTimingBreakdownView.prototype._appendRow):
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout):
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout.createBlock): Deleted.
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout.createSectionLabel): Deleted.
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout.createTimeLabel): Deleted.
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout.createTimeSection): Deleted.
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout.createRow): Deleted.
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout.emptyRow): Deleted.
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout.appendGraphRow): Deleted.
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout.appendEmptyRow): Deleted.
+        (WI.ResourceTimingBreakdownView.prototype.initialLayout.getCurrentSectionMetrics): Deleted.
+        Redesign the breakdown view.
+
 2017-12-19  Brian Burg  <bburg@apple.com>
 
         Web Inspector: InspectorTest.expectException does not handle implicitly resolved async functions correctly
index ee8b11b..62e637b 100644 (file)
@@ -233,6 +233,7 @@ localizedStrings["Connection"] = "Connection";
 localizedStrings["Connection Close Frame"] = "Connection Close Frame";
 localizedStrings["Connection Closed"] = "Connection Closed";
 localizedStrings["Connection ID"] = "Connection ID";
+localizedStrings["Connection:"] = "Connection:";
 localizedStrings["Console"] = "Console";
 localizedStrings["Console Evaluation"] = "Console Evaluation";
 localizedStrings["Console Evaluation %d"] = "Console Evaluation %d";
@@ -316,6 +317,7 @@ localizedStrings["Document Type"] = "Document Type";
 localizedStrings["Documents"] = "Documents";
 localizedStrings["Domain"] = "Domain";
 localizedStrings["Done"] = "Done";
+localizedStrings["Download"] = "Download";
 localizedStrings["Download Web Archive"] = "Download Web Archive";
 localizedStrings["Duplicate Selector"] = "Duplicate Selector";
 localizedStrings["Duplicate property"] = "Duplicate property";
@@ -720,6 +722,7 @@ localizedStrings["Pseudo Element"] = "Pseudo Element";
 localizedStrings["Query Parameters"] = "Query Parameters";
 localizedStrings["Query String"] = "Query String";
 localizedStrings["Query returned no results."] = "Query returned no results.";
+localizedStrings["Queued"] = "Queued";
 localizedStrings["Radial Gradient"] = "Radial Gradient";
 localizedStrings["Radius"] = "Radius";
 localizedStrings["Radius X"] = "Radius X";
@@ -774,6 +777,7 @@ localizedStrings["Resources"] = "Resources";
 localizedStrings["Response"] = "Response";
 localizedStrings["Response Cookies"] = "Response Cookies";
 localizedStrings["Response Headers"] = "Response Headers";
+localizedStrings["Response:"] = "Response:";
 localizedStrings["Restart (%s)"] = "Restart (%s)";
 localizedStrings["Restart animation"] = "Restart animation";
 localizedStrings["Resume Thread"] = "Resume Thread";
@@ -794,7 +798,7 @@ localizedStrings["Samples"] = "Samples";
 localizedStrings["Save File"] = "Save File";
 localizedStrings["Save Selected"] = "Save Selected";
 localizedStrings["Save configuration"] = "Save configuration";
-localizedStrings["Scheduled"] = "Scheduled";
+localizedStrings["Scheduling:"] = "Scheduling:";
 localizedStrings["Scheme"] = "Scheme";
 localizedStrings["Scope"] = "Scope";
 localizedStrings["Scope Chain"] = "Scope Chain";
@@ -896,6 +900,7 @@ localizedStrings["Start Time"] = "Start Time";
 localizedStrings["Start element selection (%s)"] = "Start element selection (%s)";
 localizedStrings["Start recording (%s)\nCreate new recording (%s)"] = "Start recording (%s)\nCreate new recording (%s)";
 localizedStrings["Start recording canvas actions. Shift-click to record a single frame."] = "Start recording canvas actions. Shift-click to record a single frame.";
+localizedStrings["Start to Finish"] = "Start to Finish";
 localizedStrings["State"] = "State";
 localizedStrings["Status"] = "Status";
 localizedStrings["Step"] = "Step";
@@ -949,6 +954,7 @@ localizedStrings["This object is referenced by internal objects"] = "This object
 localizedStrings["This property needs a value.\nClick to open autocomplete."] = "This property needs a value.\nClick to open autocomplete.";
 localizedStrings["This text resource could benefit from compression"] = "This text resource could benefit from compression";
 localizedStrings["Time"] = "Time";
+localizedStrings["Time to First Byte"] = "Time to First Byte";
 localizedStrings["Timeline"] = "Timeline";
 localizedStrings["Timeline Recording %d"] = "Timeline Recording %d";
 localizedStrings["Timelines"] = "Timelines";
@@ -964,10 +970,10 @@ localizedStrings["Toggle Classes"] = "Toggle Classes";
 localizedStrings["Toggle Visibility"] = "Toggle Visibility";
 localizedStrings["Top"] = "Top";
 localizedStrings["Top Functions"] = "Top Functions";
-localizedStrings["Total"] = "Total";
 localizedStrings["Total Time"] = "Total Time";
 localizedStrings["Total memory size at the end of the selected time range"] = "Total memory size at the end of the selected time range";
 localizedStrings["Total time"] = "Total time";
+localizedStrings["Totals:"] = "Totals:";
 localizedStrings["Trace"] = "Trace";
 localizedStrings["Trace: %s"] = "Trace: %s";
 localizedStrings["Transfer Size"] = "Transfer Size";
index 3cd6a60..ad344f2 100644 (file)
     <link rel="stylesheet" href="Views/ResourceHeadersContentView.css">
     <link rel="stylesheet" href="Views/ResourceIcons.css">
     <link rel="stylesheet" href="Views/ResourceSizesContentView.css">
-    <link rel="stylesheet" href="Views/ResourceTimingContentView.css">
     <link rel="stylesheet" href="Views/ResourceSidebarPanel.css">
     <link rel="stylesheet" href="Views/ResourceTimelineDataGridNode.css">
     <link rel="stylesheet" href="Views/ResourceTimingBreakdownView.css">
index 9b44b0e..877eb0b 100644 (file)
@@ -1411,7 +1411,7 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
             return contentElement;
         }
 
-        let breakdownView = new WI.ResourceTimingBreakdownView(resource);
+        let breakdownView = new WI.ResourceTimingBreakdownView(resource, 300);
         contentElement.appendChild(breakdownView.element);
         breakdownView.updateLayout();
 
@@ -1446,6 +1446,8 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         };
 
         let targetFrame = calculateTargetFrame();
+        if (!targetFrame)
+            return;
         if (!targetFrame.size.width && !targetFrame.size.height)
             return;
 
index 4a7e12c..fe888e1 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-.resource-timing-breakdown {
-    width: 300px;
-    padding: 10px 0;
-    text-align: center;
+.waterfall-popover .resource-timing-breakdown {
+    margin: 5px;
 }
 
-.resource-timing-breakdown .waterfall {
-    position: relative;
-    height: 40px;
-}
-
-.resource-timing-breakdown .waterfall .block {
-    top: 12px;
-    min-width: 3px;
-    height: 12px;
-}
-
-.resource-timing-breakdown .waterfall .block.request,
-.resource-timing-breakdown .waterfall .block.response {
-    top: 4px;
-    height: 28px;
-}
-
-body[dir=ltr] .resource-timing-breakdown .waterfall .block:matches(.queue, .request) {
-    border-top-left-radius: 2px;
-    border-bottom-left-radius: 2px;
-}
-
-body[dir=ltr] .resource-timing-breakdown .waterfall .block.response {
-    border-top-right-radius: 2px;
-    border-bottom-right-radius: 2px;
-}
-
-body[dir=rtl] .resource-timing-breakdown .waterfall .block:matches(.queue, .request) {
-    border-top-right-radius: 2px;
-    border-bottom-right-radius: 2px;
-}
-
-body[dir=rtl] .resource-timing-breakdown .waterfall .block.response {
-    border-top-left-radius: 2px;
-    border-bottom-left-radius: 2px;
+.resource-timing-breakdown > table > tr > td.label {
+    min-width: 80px;
+    color: gray;
 }
 
-.resource-timing-breakdown .numbers {
-    display: inline-block;
-    -webkit-margin-start: 20px;
-    text-align: start;
-}
-
-.resource-timing-breakdown .numbers > p {
-    margin: 5px 0;
-}
-
-.resource-timing-breakdown .numbers > p > .swatch {
-    display: inline-block;
-    width: 10px;
-    height: 10px;
-    -webkit-margin-start: 12px;
-    -webkit-margin-end: 3px;
-    border: 1px solid hsla(0, 0%, 25%, 0.4);
-    border-radius: 2px;
-}
-
-.resource-timing-breakdown .numbers .swatch.queue {
-    background-color: var(--network-queue-color);
-}
-
-.resource-timing-breakdown .numbers .swatch.dns {
-    background-color: var(--network-dns-color);
-}
-
-.resource-timing-breakdown .numbers .swatch.connect {
-    background-color: var(--network-connect-color);
+.resource-timing-breakdown > table > tr > td.graph {
+    position: relative;
+    width: 100%;
 }
 
-.resource-timing-breakdown .numbers .swatch.secure {
-    background-color: var(--network-secure-color);
+.resource-timing-breakdown > table > tr > td.time {
+    -webkit-padding-start: 5px;
+    text-align: end;
+    color: gray;
 }
 
-.resource-timing-breakdown .numbers .swatch.request {
-    background-color: var(--network-request-color);
+.resource-timing-breakdown > table > tr.empty {
+    height: 8px;
 }
 
-.resource-timing-breakdown .numbers .swatch.response {
-    background-color: var(--network-response-color);
+.resource-timing-breakdown > table > tr.header:not(.total-row) > td {
+    color: black;
 }
 
-.resource-timing-breakdown .numbers > p > .label {
-    font-weight: bold;
+.resource-timing-breakdown > table hr {
+    position: relative;
+    top: 2px;
+    min-width: 40px;
+    border-top: none;
+    border-left: none;
+    border-right: none;
+    border-color: gray;
+    border-bottom-width: 1px;
 }
 
-.resource-timing-breakdown .numbers > p.total {
-    margin-top: 15px;
+.resource-timing-breakdown .waterfall .block {
+    top: 1px;
+    height: 14px;
 }
index 72a9b6d..f972ada 100644 (file)
 
 WI.ResourceTimingBreakdownView = class ResourceTimingBreakdownView extends WI.View
 {
-    constructor(resource)
+    constructor(resource, fixedWidth)
     {
         super(null);
 
         console.assert(resource.timingData.startTime && resource.timingData.responseEnd, "Timing breakdown view requires a resource with timing data.");
+        console.assert(!fixedWidth || fixedWidth >= 100, "fixedWidth must be at least wide enough for strings.");
 
         this._resource = resource;
 
         this.element.classList.add("resource-timing-breakdown");
+
+        if (fixedWidth)
+            this.element.style.width = fixedWidth + "px";
     }
 
     // Protected
 
+    _appendEmptyRow()
+    {
+        let row = this._tableElement.appendChild(document.createElement("tr"));
+        row.className = "empty";
+        return row;
+    }
+
+    _appendHeaderRow(label, time, additionalClassName)
+    {
+        let row = this._tableElement.appendChild(document.createElement("tr"));
+        row.className = "header";
+        if (additionalClassName)
+            row.classList.add(additionalClassName);
+
+        let labelCell = row.appendChild(document.createElement("td"));
+        labelCell.className = "label";
+        labelCell.textContent = label;
+        labelCell.colSpan = 2;
+
+        let timeCell = row.appendChild(document.createElement("td"));
+        timeCell.className = "time";
+        if (time)
+            timeCell.textContent = time;
+        else if (time === undefined)
+            timeCell.appendChild(document.createElement("hr"));
+
+        return row;
+    }
+
+    _appendRow(label, type, startTime, endTime)
+    {
+        let row = this._tableElement.appendChild(document.createElement("tr"));
+
+        let labelCell = row.appendChild(document.createElement("td"));
+        labelCell.className = "label";
+        labelCell.textContent = label;
+
+        let duration = endTime - startTime;
+        let graphWidth = (duration / this._graphDuration) * 100;
+        let graphOffset = ((startTime - this._graphStartTime) / this._graphDuration) * 100;
+        let positionProperty = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "right" : "left";
+        let graphCell = row.appendChild(document.createElement("td"));
+        graphCell.className = "graph";
+        let block = graphCell.appendChild(document.createElement("div"));
+        block.classList.add("block", type);
+        block.style.width = graphWidth + "%";
+        block.style[positionProperty] = graphOffset + "%";
+
+        let timeCell = row.appendChild(document.createElement("td"));
+        timeCell.className = "time";
+        timeCell.textContent = Number.secondsToMillisecondsString(duration);
+
+        return row;
+    }
+
     initialLayout()
     {
         super.initialLayout();
 
-        const graphWidth = 250;
-        const graphStartOffset = 25;
-
         let {startTime, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd} = this._resource.timingData;
-        let graphStartTime = startTime;
-        let graphEndTime = responseEnd;
-        let secondsPerPixel = (responseEnd - startTime) / graphWidth;
-
-        let waterfallElement = this.element.appendChild(document.createElement("div"));
-        waterfallElement.className = "waterfall";
-
-        function appendBlock(startTime, endTime, className) {
-            let startOffset = graphStartOffset + ((startTime - graphStartTime) / secondsPerPixel);
-            let width = (endTime - startTime) / secondsPerPixel;
-            let block = waterfallElement.appendChild(document.createElement("div"));
-            block.classList.add("block", className);
-            let styleAttribute = WI.resolvedLayoutDirection() === WI.LayoutDirection.LTR ? "left" : "right";
-            block.style[styleAttribute] = startOffset + "px";
-            block.style.width = width + "px";
-        }
 
-        if (domainLookupStart) {
-            appendBlock(startTime, domainLookupStart, "queue");
-            appendBlock(domainLookupStart, connectStart || requestStart, "dns");
-        } else if (connectStart)
-            appendBlock(startTime, connectStart, "queue");
-        else if (requestStart)
-            appendBlock(startTime, requestStart, "queue");
-        if (connectStart)
-            appendBlock(connectStart, connectEnd, "connect");
-        if (secureConnectionStart)
-            appendBlock(secureConnectionStart, connectEnd, "secure");
-        appendBlock(requestStart, responseStart, "request");
-        appendBlock(responseStart, responseEnd, "response");
-
-        let numbersSection = this.element.appendChild(document.createElement("div"));
-        numbersSection.className = "numbers";
-
-        function appendRow(label, duration, paragraphClass, swatchClass) {
-            let p = numbersSection.appendChild(document.createElement("p"));
-            if (paragraphClass)
-                p.className = paragraphClass;
-
-            if (swatchClass) {
-                let swatch = p.appendChild(document.createElement("span"));
-                swatch.classList.add("swatch", swatchClass);
-            }
-
-            let labelElement = p.appendChild(document.createElement("span"));
-            labelElement.className = "label";
-            labelElement.textContent = label;
-
-            p.append(": ");
-
-            let durationElement = p.appendChild(document.createElement("span"));
-            durationElement.className = "duration";
-            durationElement.textContent = Number.secondsToMillisecondsString(duration);
-        }
+        this._tableElement = this.element.appendChild(document.createElement("table"));
+        this._tableElement.className = "waterfall";
+
+        this._graphStartTime = startTime;
+        this._graphEndTime = responseEnd;
+        this._graphDuration = this._graphEndTime - this._graphStartTime;
 
-        let scheduledDuration = (domainLookupStart || connectStart || requestStart) - startTime;
-        let connectionDuration = (connectEnd || requestStart) - (domainLookupStart || connectStart || connectEnd || requestStart);
-        let requestResponseDuration = responseEnd - requestStart;
+        this._appendHeaderRow(WI.UIString("Scheduling:"));
+        this._appendRow(WI.UIString("Queued"), "queue", startTime, domainLookupStart || connectStart || requestStart);
 
-        appendRow(WI.UIString("Scheduled"), scheduledDuration);
-        if (connectionDuration) {
-            appendRow(WI.UIString("Connection"), connectionDuration);
+        if (domainLookupStart || connectStart) {
+            this._appendEmptyRow();
+            this._appendHeaderRow(WI.UIString("Connection:"));
             if (domainLookupStart)
-                appendRow(WI.UIString("DNS"), (domainLookupEnd || connectStart) - domainLookupStart, "sub", "dns");
-            appendRow(WI.UIString("TCP"), connectEnd - connectStart, "sub", "connect");
+                this._appendRow(WI.UIString("DNS"), "dns", domainLookupStart, domainLookupEnd || connectStart || requestStart);
+            if (connectStart)
+                this._appendRow(WI.UIString("TCP"), "connect", connectStart, connectEnd || requestStart);
             if (secureConnectionStart)
-                appendRow(WI.UIString("Secure"), connectEnd - secureConnectionStart, "sub", "secure");
+                this._appendRow(WI.UIString("Secure"), "secure", secureConnectionStart, connectEnd || requestStart);
         }
-        appendRow(WI.UIString("Request & Response"), responseEnd - requestStart);
-        appendRow(WI.UIString("Waiting"), responseStart - requestStart, "sub", "request");
-        appendRow(WI.UIString("Response"), responseEnd - responseStart, "sub", "response");
-        appendRow(WI.UIString("Total"), responseEnd - startTime, "total");
+
+        this._appendEmptyRow();
+        this._appendHeaderRow(WI.UIString("Response:"));
+        this._appendRow(WI.UIString("Waiting"), "request", requestStart, responseStart);
+        this._appendRow(WI.UIString("Download"), "response", responseStart, responseEnd);
+
+        this._appendEmptyRow();
+        this._appendHeaderRow(WI.UIString("Totals:"));
+        this._appendHeaderRow(WI.UIString("Time to First Byte"), Number.secondsToMillisecondsString(responseStart - startTime), "total-row");
+        this._appendHeaderRow(WI.UIString("Start to Finish"), Number.secondsToMillisecondsString(responseEnd - startTime), "total-row");
     }
 };
diff --git a/Source/WebInspectorUI/UserInterface/Views/ResourceTimingContentView.css b/Source/WebInspectorUI/UserInterface/Views/ResourceTimingContentView.css
deleted file mode 100644 (file)
index a8f0c4e..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-.resource-timing {
-    font-family: '-webkit-system-font';
-}
-
-.resource-timing > .content {
-    width: 550px;
-    margin: 0 auto;
-}
-
-.resource-timing > .content .label {
-    color: gray;
-}
-
-.resource-timing > .content > section.timing {
-    padding: 20px 0;
-}
-
-.resource-timing > .content > section.timing > ul {
-    margin: 0;
-    padding: 0;
-    list-style-type: none;
-}
-
-.resource-timing > .content > section.timing > ul > li {
-    position: relative;
-    height: 20px;
-    padding: 1px 0;
-    line-height: 18px;
-}
-
-.resource-timing > .content > section.timing > .waterfall {
-    width: 500px;
-    margin: auto;
-}
-
-.resource-timing > .content > section.timing > .waterfall .block {
-    top: 4px;
-    min-width: 1px;
-    height: 12px;
-}
-
-.resource-timing > .content > section.timing > ul > li > .row-label {
-    display: inline-block;
-    min-width: 70px;
-    color: black;
-}
-
-.resource-timing > .content > section.timing > ul > li > .row-label {
-    text-align: end;
-}
-
-.resource-timing > .content > section.timing > ul > li > .time-label {
-    position: absolute;
-    top: 1px;
-    color: gray;
-}
-
-.resource-timing > .content > section.timing > ul > li.total .block {
-    display: none;
-}
-
-.resource-timing > .content > section.timing > ul > li.total .time-label {
-    color: black;
-}
-
-.resource-timing > .content > section.timing .indeterminate-progress-spinner {
-    margin: 0 auto;
-}
-
-.resource-timing > .content > section.timing .empty {
-    text-align: center;
-    color: gray;
-}
index c32fb2c..e84a5f3 100644 (file)
@@ -46,12 +46,6 @@ WI.ResourceTimingContentView = class ResourceTimingContentView extends WI.Conten
     {
         super.initialLayout();
 
-        let contentElement = this.element.appendChild(document.createElement("div"));
-        contentElement.className = "content";
-
-        this._timingSection = contentElement.appendChild(document.createElement("section"));
-        this._timingSection.className = "timing";
-
         this._refreshTimingSection();
 
         this._needsTimingRefresh = false;
@@ -78,79 +72,29 @@ WI.ResourceTimingContentView = class ResourceTimingContentView extends WI.Conten
 
     _refreshTimingSection()
     {
-        this._timingSection.removeChildren();
+        this.element.removeChildren();
 
         if (!this._resource.hasResponse()) {
             let spinner = new WI.IndeterminateProgressSpinner;
-            this._timingSection.appendChild(spinner.element);
+            this.element.appendChild(spinner.element);
             return;
         }
 
         if (!this._resource.timingData.startTime || !this._resource.timingData.responseEnd) {
-            let p = this._timingSection.appendChild(document.createElement("p"));
-            p.className = "empty";
-            p.textContent = WI.UIString("Resource does not have timing data");
+            const isError = false;
+            this.element.appendChild(WI.createMessageTextView(WI.UIString("Resource does not have timing data"), isError));
             return;
         }
 
-        // FIXME: Converge on using WI.ResourceTimingBreakdownView when a design is finalized.
-
-        let listElement = this._timingSection.appendChild(document.createElement("ul"));
-        listElement.className = "waterfall"; // Include waterfall block styles.
-
-        const graphWidth = 380;
-        const graphStartOffset = 80;
-
-        let {startTime, domainLookupStart, domainLookupEnd, connectStart, connectEnd, secureConnectionStart, requestStart, responseStart, responseEnd} = this._resource.timingData;
-        let graphStartTime = startTime;
-        let graphEndTime = responseEnd;
-        let secondsPerPixel = (responseEnd - startTime) / graphWidth;
-
-        function createBlock(startTime, endTime, className, makeEmpty) {
-            let startOffset = graphStartOffset + ((startTime - graphStartTime) / secondsPerPixel);
-            let width = makeEmpty ? 1 : (endTime - startTime) / secondsPerPixel;
-            let block = document.createElement("div");
-            block.classList.add("block", className);
-            let property = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "right" : "left";
-            block.style[property] = startOffset + "px";
-            block.style.width = width + "px";
-            return block;
-        }
-
-        function createTimeLabel(endTime, label) {
-            let positionOffset = graphStartOffset + ((endTime - graphStartTime) / secondsPerPixel);
-            positionOffset += 3;
-            let timeLabel = document.createElement("div");
-            timeLabel.className = "time-label";
-            timeLabel.textContent = label;
-            let property = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "right" : "left";
-            timeLabel.style[property] = positionOffset + "px";
-            return timeLabel;
-        }
+        let contentElement = this.element.appendChild(document.createElement("div"));
+        contentElement.className = "content";
 
-        function createRow(label, startTime, endTime, className) {
-            let row = document.createElement("li");
-            let labelElement = row.appendChild(document.createElement("span"));
-            labelElement.className = "row-label";
-            labelElement.textContent = label;
-            row.appendChild(createBlock(startTime, endTime, className));
-            row.appendChild(createTimeLabel(endTime, Number.secondsToMillisecondsString(endTime - startTime)));
-            return row;
-        }
+        let timingSection = contentElement.appendChild(document.createElement("section"));
+        timingSection.className = "timing";
 
-        listElement.appendChild(createRow(WI.UIString("Scheduled"), startTime, domainLookupStart || connectStart || requestStart, "queue"));
-        if (domainLookupStart)
-            listElement.appendChild(createRow(WI.UIString("DNS"), domainLookupStart, domainLookupEnd || connectStart || requestStart, "dns"));
-        if (connectStart)
-            listElement.appendChild(createRow(WI.UIString("TCP"), connectStart, connectEnd || requestStart, "connect"));
-        if (secureConnectionStart)
-            listElement.appendChild(createRow(WI.UIString("Secure"), secureConnectionStart, connectEnd || requestStart, "secure"));
-        listElement.appendChild(createRow(WI.UIString("Request"), requestStart, responseStart, "request"));
-        listElement.appendChild(createRow(WI.UIString("Response"), responseStart, responseEnd, "response"));
-
-        let totalRow = createRow(WI.UIString("Total"), startTime, responseEnd, "total");
-        listElement.appendChild(totalRow);
-        totalRow.classList.add("total");
+        let breakdownView = new WI.ResourceTimingBreakdownView(this._resource);
+        timingSection.appendChild(breakdownView.element);
+        breakdownView.updateLayout();
     }
 
     _resourceMetricsDidChange(event)