Web Inspector: Make showing a content view work in the tab world
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / NetworkTimelineView.js
1 /*
2  * Copyright (C) 2014 Apple 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
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.NetworkTimelineView = function(timeline, extraArguments)
27 {
28     WebInspector.TimelineView.call(this, timeline, extraArguments);
29
30     console.assert(timeline.type === WebInspector.TimelineRecord.Type.Network);
31
32     this.navigationSidebarTreeOutline.element.classList.add(WebInspector.NavigationSidebarPanel.HideDisclosureButtonsStyleClassName);
33     this.navigationSidebarTreeOutline.element.classList.add(WebInspector.NetworkTimelineView.TreeOutlineStyleClassName);
34
35     var columns = {domain: {}, type: {}, method: {}, scheme: {}, statusCode: {}, cached: {}, size: {}, transferSize: {}, requestSent: {}, latency: {}, duration: {}};
36
37     columns.domain.title = WebInspector.UIString("Domain");
38     columns.domain.width = "10%";
39
40     columns.type.title = WebInspector.UIString("Type");
41     columns.type.width = "8%";
42
43     var typeToLabelMap = new Map;
44     for (var key in WebInspector.Resource.Type) {
45         var value = WebInspector.Resource.Type[key];
46         typeToLabelMap.set(value, WebInspector.Resource.displayNameForType(value, true));
47     }
48
49     columns.type.scopeBar = WebInspector.TimelineDataGrid.createColumnScopeBar("network", typeToLabelMap);
50
51     columns.method.title = WebInspector.UIString("Method");
52     columns.method.width = "6%";
53
54     columns.scheme.title = WebInspector.UIString("Scheme");
55     columns.scheme.width = "6%";
56
57     columns.statusCode.title = WebInspector.UIString("Status");
58     columns.statusCode.width = "6%";
59
60     columns.cached.title = WebInspector.UIString("Cached");
61     columns.cached.width = "6%";
62
63     columns.size.title = WebInspector.UIString("Size");
64     columns.size.width = "8%";
65     columns.size.aligned = "right";
66
67     columns.transferSize.title = WebInspector.UIString("Transfered");
68     columns.transferSize.width = "8%";
69     columns.transferSize.aligned = "right";
70
71     columns.requestSent.title = WebInspector.UIString("Start Time");
72     columns.requestSent.width = "9%";
73     columns.requestSent.aligned = "right";
74
75     columns.latency.title = WebInspector.UIString("Latency");
76     columns.latency.width = "9%";
77     columns.latency.aligned = "right";
78
79     columns.duration.title = WebInspector.UIString("Duration");
80     columns.duration.width = "9%";
81     columns.duration.aligned = "right";
82
83     for (var column in columns)
84         columns[column].sortable = true;
85
86     this._dataGrid = new WebInspector.TimelineDataGrid(this.navigationSidebarTreeOutline, columns);
87     this._dataGrid.addEventListener(WebInspector.TimelineDataGrid.Event.FiltersDidChange, this._dataGridFiltersDidChange, this);
88     this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._dataGridNodeSelected, this);
89     this._dataGrid.sortColumnIdentifier = "requestSent";
90     this._dataGrid.sortOrder = WebInspector.DataGrid.SortOrder.Ascending;
91
92     this.element.classList.add(WebInspector.NetworkTimelineView.StyleClassName);
93     this.element.appendChild(this._dataGrid.element);
94
95     timeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._networkTimelineRecordAdded, this);
96
97     this._pendingRecords = [];
98 };
99
100 WebInspector.NetworkTimelineView.StyleClassName = "network";
101 WebInspector.NetworkTimelineView.TreeOutlineStyleClassName = "network";
102
103 WebInspector.NetworkTimelineView.prototype = {
104     constructor: WebInspector.NetworkTimelineView,
105     __proto__: WebInspector.TimelineView.prototype,
106
107     // Public
108
109     get navigationSidebarTreeOutlineLabel()
110     {
111         return WebInspector.UIString("Resources");
112     },
113
114     shown: function()
115     {
116         WebInspector.ContentView.prototype.shown.call(this);
117
118         this._dataGrid.shown();
119     },
120
121     hidden: function()
122     {
123         this._dataGrid.hidden();
124
125         WebInspector.ContentView.prototype.hidden.call(this);
126     },
127
128     updateLayout: function()
129     {
130         WebInspector.TimelineView.prototype.updateLayout.call(this);
131
132         this._dataGrid.updateLayout();
133
134         this._processPendingRecords();
135     },
136
137     matchTreeElementAgainstCustomFilters: function(treeElement)
138     {
139         return this._dataGrid.treeElementMatchesActiveScopeFilters(treeElement);
140     },
141
142     reset: function()
143     {
144         WebInspector.TimelineView.prototype.reset.call(this);
145
146         this._dataGrid.reset();
147     },
148
149     // Protected
150
151     showContentViewForTreeElement: function(treeElement)
152     {
153         if (treeElement instanceof WebInspector.ResourceTreeElement || treeElement instanceof WebInspector.ScriptTreeElement) {
154             WebInspector.showSourceCode(treeElement.representedObject);
155             return true;
156         }
157
158         console.error("Unknown tree element selected.", treeElement);
159         return false;
160     },
161
162     treeElementPathComponentSelected: function(event)
163     {
164         var dataGridNode = this._dataGrid.dataGridNodeForTreeElement(event.data.pathComponent.generalTreeElement);
165         if (!dataGridNode)
166             return;
167         dataGridNode.revealAndSelect();
168     },
169
170     treeElementSelected: function(treeElement, selectedByUser)
171     {
172         if (this._dataGrid.shouldIgnoreSelectionEvent())
173             return false;
174
175         WebInspector.TimelineView.prototype.treeElementSelected.call(this, treeElement, selectedByUser);
176     },
177
178     // Private
179
180     _processPendingRecords: function()
181     {
182         if (!this._pendingRecords.length)
183             return;
184
185         for (var resourceTimelineRecord of this._pendingRecords) {
186             // Skip the record if it already exists in the tree.
187             var treeElement = this.navigationSidebarTreeOutline.findTreeElement(resourceTimelineRecord.resource);
188             if (treeElement)
189                 continue;
190
191             treeElement = new WebInspector.ResourceTreeElement(resourceTimelineRecord.resource);
192             var dataGridNode = new WebInspector.ResourceTimelineDataGridNode(resourceTimelineRecord, false, this);
193
194             this._dataGrid.addRowInSortOrder(treeElement, dataGridNode);
195         }
196
197         this._pendingRecords = [];
198     },
199
200     _networkTimelineRecordAdded: function(event)
201     {
202         var resourceTimelineRecord = event.data.record;
203         console.assert(resourceTimelineRecord instanceof WebInspector.ResourceTimelineRecord);
204
205         this._pendingRecords.push(resourceTimelineRecord);
206
207         this.needsLayout();
208     },
209
210     _dataGridFiltersDidChange: function(event)
211     {
212         this.timelineSidebarPanel.updateFilter();
213     },
214
215     _dataGridNodeSelected: function(event)
216     {
217         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
218     },
219
220     _updateTreeElementWithCloseButton: function(treeElement)
221     {
222         if (this._closeStatusButton) {
223             treeElement.status = this._closeStatusButton.element;
224             return;
225         }
226
227         wrappedSVGDocument(platformImagePath("Close.svg"), null, WebInspector.UIString("Close resource view"), function(element) {
228             this._closeStatusButton = new WebInspector.TreeElementStatusButton(element);
229             this._closeStatusButton.addEventListener(WebInspector.TreeElementStatusButton.Event.Clicked, this._closeStatusButtonClicked, this);
230             if (treeElement === this.navigationSidebarTreeOutline.selectedTreeElement)
231                 this._updateTreeElementWithCloseButton(treeElement);
232         }.bind(this));
233     },
234
235     _closeStatusButtonClicked: function(event)
236     {
237         this.navigationSidebarTreeOutline.selectedTreeElement.deselect();
238         this.timelineSidebarPanel.showTimelineViewForTimeline(this.representedObject);
239     }
240 };