Title: [203843] trunk/Source/WebInspectorUI
Revision
203843
Author
[email protected]
Date
2016-07-28 14:38:50 -0700 (Thu, 28 Jul 2016)

Log Message

Web Inspector: Waterfall view should be visible in Network tab and Network Timeline
https://bugs.webkit.org/show_bug.cgi?id=160061

Patch by Johan K. Jensen <[email protected]> on 2016-07-28
Reviewed by Joseph Pecoraro.

Adds a Timeline-column (waterfall) to the Network tab and Network Timeline.

* Localizations/en.lproj/localizedStrings.js:
Add "Timeline" localized string.

* UserInterface/Views/NetworkGridContentView.js:
(WebInspector.NetworkGridContentView):
Add the Timeline-column with a TimelineRuler as the headerview,
and properties for updating current time.

(WebInspector.NetworkGridContentView.prototype.get secondsPerPixel):
(WebInspector.NetworkGridContentView.prototype.get startTime):
(WebInspector.NetworkGridContentView.prototype.get currentTime):
(WebInspector.NetworkGridContentView.prototype.get endTime):
Acting as a graphDataSource used by TimelineDataGridNode.

(WebInspector.NetworkGridContentView.prototype.shown):
(WebInspector.NetworkGridContentView.prototype.reset):
(WebInspector.NetworkGridContentView.prototype.layout):
Refresh graphs and update the TimelineRuler on layout changes.

(WebInspector.NetworkGridContentView.prototype._networkTimelineRecordAdded):
Add listeners for when resources are finished to stop the timer.

(WebInspector.NetworkGridContentView.prototype._update):
(WebInspector.NetworkGridContentView.prototype._startUpdatingCurrentTime):
(WebInspector.NetworkGridContentView.prototype._stopUpdatingCurrentTime):
Adding a timer which updates the TimelineRuler and the layout
if any non-finished requests are running.

* UserInterface/Views/NetworkTimelineView.js:
(WebInspector.NetworkTimelineView):
Add the Timeline-column with a TimelineRuler as the headerview.

(WebInspector.NetworkTimelineView.prototype.get secondsPerPixel):
(WebInspector.NetworkTimelineView.prototype.layout):
Refresh graphs on layout changes.

* UserInterface/Views/TimelineDataGrid.css:
(.tree-outline.timeline-data-grid .item:hover .subtitle):
(.data-grid.timeline th):
(.data-grid.timeline th.graph-column > .timeline-ruler):
(.data-grid.timeline td.graph-column):
(.data-grid.timeline td.graph-column > .cell-content):
(.data-grid.timeline td.graph-column .timeline-record-bar):

Modified Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (203842 => 203843)


--- trunk/Source/WebInspectorUI/ChangeLog	2016-07-28 21:19:06 UTC (rev 203842)
+++ trunk/Source/WebInspectorUI/ChangeLog	2016-07-28 21:38:50 UTC (rev 203843)
@@ -1,3 +1,56 @@
+2016-07-28  Johan K. Jensen  <[email protected]>
+
+        Web Inspector: Waterfall view should be visible in Network tab and Network Timeline
+        https://bugs.webkit.org/show_bug.cgi?id=160061
+
+        Reviewed by Joseph Pecoraro.
+
+        Adds a Timeline-column (waterfall) to the Network tab and Network Timeline.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        Add "Timeline" localized string.
+
+        * UserInterface/Views/NetworkGridContentView.js:
+        (WebInspector.NetworkGridContentView):
+        Add the Timeline-column with a TimelineRuler as the headerview,
+        and properties for updating current time.
+
+        (WebInspector.NetworkGridContentView.prototype.get secondsPerPixel):
+        (WebInspector.NetworkGridContentView.prototype.get startTime):
+        (WebInspector.NetworkGridContentView.prototype.get currentTime):
+        (WebInspector.NetworkGridContentView.prototype.get endTime):
+        Acting as a graphDataSource used by TimelineDataGridNode.
+
+        (WebInspector.NetworkGridContentView.prototype.shown):
+        (WebInspector.NetworkGridContentView.prototype.reset):
+        (WebInspector.NetworkGridContentView.prototype.layout):
+        Refresh graphs and update the TimelineRuler on layout changes.
+
+        (WebInspector.NetworkGridContentView.prototype._networkTimelineRecordAdded):
+        Add listeners for when resources are finished to stop the timer.
+
+        (WebInspector.NetworkGridContentView.prototype._update):
+        (WebInspector.NetworkGridContentView.prototype._startUpdatingCurrentTime):
+        (WebInspector.NetworkGridContentView.prototype._stopUpdatingCurrentTime):
+        Adding a timer which updates the TimelineRuler and the layout
+        if any non-finished requests are running.
+
+        * UserInterface/Views/NetworkTimelineView.js:
+        (WebInspector.NetworkTimelineView):
+        Add the Timeline-column with a TimelineRuler as the headerview.
+
+        (WebInspector.NetworkTimelineView.prototype.get secondsPerPixel):
+        (WebInspector.NetworkTimelineView.prototype.layout):
+        Refresh graphs on layout changes.
+
+        * UserInterface/Views/TimelineDataGrid.css:
+        (.tree-outline.timeline-data-grid .item:hover .subtitle):
+        (.data-grid.timeline th):
+        (.data-grid.timeline th.graph-column > .timeline-ruler):
+        (.data-grid.timeline td.graph-column):
+        (.data-grid.timeline td.graph-column > .cell-content):
+        (.data-grid.timeline td.graph-column .timeline-record-bar):
+
 2016-07-28  Chris Dumez  <[email protected]>
 
         Parameter to table.deleteRow() / body.deleteRow() should be mandatory

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (203842 => 203843)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2016-07-28 21:19:06 UTC (rev 203842)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2016-07-28 21:38:50 UTC (rev 203843)
@@ -706,6 +706,7 @@
 localizedStrings["This property needs a value.\nClick to open autocomplete."] = "This property needs a value.\nClick to open autocomplete.";
 localizedStrings["Time"] = "Time";
 localizedStrings["Time until the load event fired, click to show the Network Requests timeline"] = "Time until the load event fired, click to show the Network Requests timeline";
+localizedStrings["Timeline"] = "Timeline";
 localizedStrings["Timeline Recording %d"] = "Timeline Recording %d";
 localizedStrings["Timelines"] = "Timelines";
 localizedStrings["Timer %s Fired"] = "Timer %s Fired";

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkGridContentView.js (203842 => 203843)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkGridContentView.js	2016-07-28 21:19:06 UTC (rev 203842)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkGridContentView.js	2016-07-28 21:38:50 UTC (rev 203843)
@@ -37,7 +37,7 @@
         this._contentTreeOutline = this._networkSidebarPanel.contentTreeOutline;
         this._contentTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
 
-        var columns = {domain: {}, type: {}, method: {}, scheme: {}, statusCode: {}, cached: {}, size: {}, transferSize: {}, requestSent: {}, latency: {}, duration: {}};
+        var columns = {domain: {}, type: {}, method: {}, scheme: {}, statusCode: {}, cached: {}, size: {}, transferSize: {}, requestSent: {}, latency: {}, duration: {}, graph: {}};
 
         columns.domain.title = WebInspector.UIString("Domain");
         columns.domain.width = "10%";
@@ -80,6 +80,14 @@
         for (var column in columns)
             columns[column].sortable = true;
 
+        this._timelineRuler = new WebInspector.TimelineRuler;
+        this._timelineRuler.allowsClippedLabels = true;
+
+        columns.graph.title = WebInspector.UIString("Timeline");
+        columns.graph.width = "15%";
+        columns.graph.headerView = this._timelineRuler;
+        columns.graph.sortable = false;
+
         this._dataGrid = new WebInspector.TimelineDataGrid(columns, this._contentTreeOutline);
         this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._dataGridNodeSelected, this);
         this._dataGrid.sortColumnIdentifier = "requestSent";
@@ -97,10 +105,18 @@
         this._clearNetworkItemsNavigationItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._clearNetworkItems, this);
 
         this._pendingRecords = [];
+        this._loadingResourceCount = 0;
+        this._lastUpdateTimestamp = NaN;
+        this._scheduledCurrentTimeUpdateIdentifier = undefined;
     }
 
     // Public
 
+    get secondsPerPixel() { return this._timelineRuler.secondsPerPixel; }
+    get startTime() { return this._timelineRuler.startTime; }
+    get currentTime() { return this.endTime || this.startTime; }
+    get endTime() { return this._timelineRuler.endTime; }
+
     get selectionPathComponents()
     {
         if (!this._contentTreeOutline.selectedTreeElement || this._contentTreeOutline.selectedTreeElement.hidden)
@@ -126,6 +142,9 @@
         super.shown();
 
         this._dataGrid.shown();
+
+        if (this._loadingResourceCount && !this._scheduledCurrentTimeUpdateIdentifier)
+            this._startUpdatingCurrentTime();
     }
 
     hidden()
@@ -144,6 +163,15 @@
     {
         this._contentTreeOutline.removeChildren();
         this._dataGrid.reset();
+
+        if (this._scheduledCurrentTimeUpdateIdentifier)
+            this._stopUpdatingCurrentTime();
+
+        this._loadingResourceCount = 0;
+        this._lastUpdateTimestamp = NaN;
+
+        this._timelineRuler.startTime = 0;
+        this._timelineRuler.endTime = 0;
     }
 
     // Protected
@@ -150,6 +178,12 @@
 
     layout()
     {
+        this._timelineRuler.zeroTime = this.zeroTime;
+        this._timelineRuler.startTime = this.zeroTime;
+
+        for (let dataGridNode of this._dataGrid.children)
+            dataGridNode.refreshGraph();
+
         this._processPendingRecords();
     }
 
@@ -185,9 +219,35 @@
         var resourceTimelineRecord = event.data.record;
         console.assert(resourceTimelineRecord instanceof WebInspector.ResourceTimelineRecord);
 
+        let update = (event) => {
+            if (event.target[WebInspector.NetworkGridContentView.ResourceDidFinishOrFail])
+                return;
+
+            event.target.removeEventListener(null, null, this);
+            event.target[WebInspector.NetworkGridContentView.ResourceDidFinishOrFail] = true;
+
+            this._loadingResourceCount--;
+            if (this._loadingResourceCount)
+                return;
+
+            this.debounce(250)._stopUpdatingCurrentTime();
+        };
+
         this._pendingRecords.push(resourceTimelineRecord);
 
         this.needsLayout();
+
+        let resource = resourceTimelineRecord.resource;
+        if (resource.finished || resource.failed || resource.canceled)
+            return;
+
+        resource[WebInspector.NetworkGridContentView.ResourceDidFinishOrFail] = false;
+        resource.addEventListener(WebInspector.Resource.Event.LoadingDidFinish, update, this);
+        resource.addEventListener(WebInspector.Resource.Event.LoadingDidFail, update, this);
+
+        this._loadingResourceCount++;
+        if (this._loadingResourceCount && !this._scheduledCurrentTimeUpdateIdentifier)
+            this._startUpdatingCurrentTime();
     }
 
     _treeElementPathComponentSelected(event)
@@ -222,4 +282,50 @@
     _clearNetworkItems(event) {
         this.reset();
     }
+
+    _update(timestamp)
+    {
+        console.assert(this._scheduledCurrentTimeUpdateIdentifier);
+
+        let startTime = this.startTime;
+        let currentTime = this.currentTime;
+        let endTime = this.endTime;
+        let timespanSinceLastUpdate = (timestamp - this._lastUpdateTimestamp) / 1000 || 0;
+
+        currentTime += timespanSinceLastUpdate;
+
+        this._timelineRuler.endTime = currentTime;
+        this._lastUpdateTimestamp = timestamp;
+        this.updateLayout();
+
+        this._scheduledCurrentTimeUpdateIdentifier = requestAnimationFrame(this._updateCallback);
+    }
+
+    _startUpdatingCurrentTime()
+    {
+        console.assert(!this._scheduledCurrentTimeUpdateIdentifier);
+        if (this._scheduledCurrentTimeUpdateIdentifier)
+            return;
+
+        // Don't update the current time if the Inspector is not visible, as the requestAnimationFrames won't work.
+        if (!WebInspector.visible)
+            return;
+
+        if (!this._updateCallback)
+            this._updateCallback = this._update.bind(this);
+
+        this._scheduledCurrentTimeUpdateIdentifier = requestAnimationFrame(this._updateCallback);
+    }
+
+    _stopUpdatingCurrentTime()
+    {
+        console.assert(this._scheduledCurrentTimeUpdateIdentifier);
+        if (!this._scheduledCurrentTimeUpdateIdentifier)
+            return;
+
+        cancelAnimationFrame(this._scheduledCurrentTimeUpdateIdentifier);
+        this._scheduledCurrentTimeUpdateIdentifier = undefined;
+    }
 };
+
+WebInspector.NetworkGridContentView.ResourceDidFinishOrFail = Symbol("ResourceDidFinishOrFail");

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js (203842 => 203843)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js	2016-07-28 21:19:06 UTC (rev 203842)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js	2016-07-28 21:38:50 UTC (rev 203843)
@@ -31,7 +31,7 @@
 
         console.assert(timeline.type === WebInspector.TimelineRecord.Type.Network);
 
-        let columns = {name: {}, domain: {}, type: {}, method: {}, scheme: {}, statusCode: {}, cached: {}, size: {}, transferSize: {}, requestSent: {}, latency: {}, duration: {}};
+        let columns = {name: {}, domain: {}, type: {}, method: {}, scheme: {}, statusCode: {}, cached: {}, size: {}, transferSize: {}, requestSent: {}, latency: {}, duration: {}, graph: {}};
 
         columns.name.title = WebInspector.UIString("Name");
         columns.name.icon = true;
@@ -39,10 +39,10 @@
         columns.name.locked = true;
 
         columns.domain.title = WebInspector.UIString("Domain");
-        columns.domain.width = "10%";
+        columns.domain.width = "8%";
 
         columns.type.title = WebInspector.UIString("Type");
-        columns.type.width = "8%";
+        columns.type.width = "7%";
 
         var typeToLabelMap = new Map;
         for (var key in WebInspector.Resource.Type) {
@@ -54,16 +54,16 @@
         this._scopeBar = columns.type.scopeBar;
 
         columns.method.title = WebInspector.UIString("Method");
-        columns.method.width = "6%";
+        columns.method.width = "4%";
 
         columns.scheme.title = WebInspector.UIString("Scheme");
-        columns.scheme.width = "6%";
+        columns.scheme.width = "4%";
 
         columns.statusCode.title = WebInspector.UIString("Status");
-        columns.statusCode.width = "6%";
+        columns.statusCode.width = "4%";
 
         columns.cached.title = WebInspector.UIString("Cached");
-        columns.cached.width = "6%";
+        columns.cached.width = "4%";
 
         columns.size.title = WebInspector.UIString("Size");
         columns.size.width = "8%";
@@ -88,6 +88,14 @@
         for (var column in columns)
             columns[column].sortable = true;
 
+        this._timelineRuler = new WebInspector.TimelineRuler;
+        this._timelineRuler.allowsClippedLabels = true;
+
+        columns.graph.title = WebInspector.UIString("Timeline");
+        columns.graph.width = "15%";
+        columns.graph.headerView = this._timelineRuler;
+        columns.graph.sortable = false;
+
         this._dataGrid = new WebInspector.TimelineDataGrid(columns);
         this._dataGrid.sortDelegate = this;
         this._dataGrid.sortColumnIdentifier = "requestSent";
@@ -107,6 +115,8 @@
 
     // Public
 
+    get secondsPerPixel() { return this._timelineRuler.secondsPerPixel; }
+
     get selectionPathComponents()
     {
         if (!this._dataGrid.selectedNode || this._dataGrid.selectedNode.hidden)
@@ -197,6 +207,15 @@
 
     layout()
     {
+        this.endTime = Math.min(this.endTime, this.currentTime);
+
+        this._timelineRuler.zeroTime = this.zeroTime;
+        this._timelineRuler.startTime = this.startTime;
+        this._timelineRuler.endTime = this.endTime;
+
+        for (let dataGridNode of this._resourceDataGridNodeMap.values())
+            dataGridNode.refreshGraph();
+
         this._processPendingRecords();
     }
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGrid.css (203842 => 203843)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGrid.css	2016-07-28 21:19:06 UTC (rev 203842)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGrid.css	2016-07-28 21:38:50 UTC (rev 203843)
@@ -35,4 +35,26 @@
 
 .tree-outline.timeline-data-grid .item:hover .subtitle {
     color: white;
-}
\ No newline at end of file
+}
+
+.data-grid.timeline th {
+    border-top: none;
+}
+
+.data-grid.timeline th.graph-column > .timeline-ruler {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+}
+
+.data-grid.timeline td.graph-column {
+    padding: 2px 0;
+}
+
+.data-grid.timeline td.graph-column > .cell-content {
+    position: relative;
+}
+
+.data-grid.timeline td.graph-column .timeline-record-bar {
+    top: 2px;
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to