Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(321)

Side by Side Diff: chrome/browser/resources/net_internals/timeline_view.js

Issue 8474001: Add a timeline view to about:net-internals. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Comment fix Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 /**
6 * TimelineView displays a zoomable and scrollable graph of a number of values
7 * over time. The TimelineView class itself is responsible primarily for
8 * updating the TimelineDataSeries its GraphView displays.
9 */
10 var TimelineView = (function() {
11 'use strict';
12
13 // We inherit from ResizableVerticalSplitView.
14 var superClass = ResizableVerticalSplitView;
15
16 /**
17 * @constructor
18 */
19 function TimelineView() {
20 assertFirstConstructorCall(TimelineView);
21
22 this.graphView_ = new TimelineGraphView(
23 TimelineView.GRAPH_DIV_ID,
24 TimelineView.GRAPH_CANVAS_ID,
25 TimelineView.SCROLLBAR_DIV_ID,
26 TimelineView.SCROLLBAR_INNER_DIV_ID);
27
28 // Call superclass's constructor.
29 superClass.call(this,
30 new DivView(TimelineView.SELECTION_DIV_ID),
31 this.graphView_,
32 new DivView(TimelineView.VERTICAL_SPLITTER_ID));
33
34 this.setLeftSplit(250);
35
36 // Interval id returned by window.setInterval for update timer.
37 this.updateIntervalId_ = null;
38
39 // List of DataSeries. These are shared with the TimelineGraphView. The
40 // TimelineView updates their state, the TimelineGraphView reads their
41 // state and draws them.
42 this.dataSeries_ = [];
43
44 // DataSeries depend on some of the global constants, so they're only
45 // created once constants have been received. We also use this message to
46 // recreate DataSeries when log files are being loaded.
47 g_browser.addConstantsObserver(this);
48
49 // We observe new log entries to determine the range of the graph, and pass
50 // them on to each DataSource. We initialize the graph range to initially
51 // include all events, but after that, we only update it to be the current
52 // time on a timer.
53 g_browser.sourceTracker.addLogEntryObserver(this);
54 this.graphRangeInitialized_ = false;
55 }
56
57 // ID for special HTML element in category_tabs.html
58 TimelineView.TAB_HANDLE_ID = 'tab-handle-timeline';
59
60 // IDs for special HTML elements in timeline_view.html
61 TimelineView.GRAPH_DIV_ID = 'timeline-view-graph-div';
62 TimelineView.GRAPH_CANVAS_ID = 'timeline-view-graph-canvas';
63 TimelineView.VERTICAL_SPLITTER_ID = 'timeline-view-vertical-splitter';
64 TimelineView.SELECTION_DIV_ID = 'timeline-view-selection-div';
65 TimelineView.SCROLLBAR_DIV_ID = 'timeline-view-scrollbar-div';
66 TimelineView.SCROLLBAR_INNER_DIV_ID = 'timeline-view-scrollbar-inner-div';
67
68 TimelineView.OPEN_SOCKETS_ID = 'timeline-view-open-sockets';
69 TimelineView.IN_USE_SOCKETS_ID = 'timeline-view-in-use-sockets';
70 TimelineView.URL_REQUESTS_ID = 'timeline-view-url-requests';
71 TimelineView.DNS_REQUESTS_ID = 'timeline-view-dns-requests';
72 TimelineView.BYTES_RECEIVED_ID = 'timeline-view-bytes-received';
73 TimelineView.BYTES_SENT_ID = 'timeline-view-bytes-sent';
74 TimelineView.DISK_CACHE_BYTES_READ_ID =
75 'timeline-view-disk-cache-bytes-read';
76 TimelineView.DISK_CACHE_BYTES_WRITTEN_ID =
77 'timeline-view-disk-cache-bytes-written';
78
79 // Class used for hiding the colored squares next to the labels for the
80 // lines.
81 TimelineView.HIDDEN_CLASS = 'timeline-view-hidden';
82
83 cr.addSingletonGetter(TimelineView);
84
85 // Frequency with which we increase update the end date to be the current
86 // time, when actively capturing events.
87 var UPDATE_INTERVAL_MS = 2000;
88
89 TimelineView.prototype = {
90 // Inherit the superclass's methods.
91 __proto__: superClass.prototype,
92
93 setGeometry: function(left, top, width, height) {
94 superClass.prototype.setGeometry.call(this, left, top, width, height);
95 },
96
97 show: function(isVisible) {
98 superClass.prototype.show.call(this, isVisible);
99 // If we're hidden or viewing a log file, make sure no interval is
100 // running.
101 if (!isVisible || MainView.isViewingLoadedLog()) {
102 this.setUpdateEndDateInterval_(0);
103 return;
104 }
105
106 // Otherwise, update the visible range on a timer.
107 this.setUpdateEndDateInterval_(UPDATE_INTERVAL_MS);
108 this.updateEndDate_();
109 },
110
111 /**
112 * Starts calling the GraphView's updateEndDate function every |intervalMs|
113 * milliseconds. If |intervalMs| is 0, stops calling the function.
114 */
115 setUpdateEndDateInterval_: function(intervalMs) {
116 if (this.updateIntervalId_ !== null) {
117 window.clearInterval(this.updateIntervalId_);
118 this.updateIntervalId_ = null;
119 }
120 if (intervalMs > 0) {
121 this.updateIntervalId_ =
122 window.setInterval(this.updateEndDate_.bind(this), intervalMs);
123 }
124 },
125
126 updateEndDate_: function() {
127 this.graphView_.updateEndDate();
128 },
129
130 onLoadLogFinish: function(data) {
131 this.setUpdateEndDateInterval_(0);
132 return true;
133 },
134
135 /**
136 * Updates the visibility state of |dataSeries| to correspond to the
137 * current checked state of |checkBox|. Also updates the class of
138 * |listItem| based on the new visibility state.
139 */
140 updateDataSeriesVisibility_: function(dataSeries, listItem, checkBox) {
141 dataSeries.show(checkBox.checked);
142 changeClassName(listItem, TimelineView.HIDDEN_CLASS, !checkBox.checked);
143 },
144
145 dataSeriesClicked_: function(dataSeries, listItem, checkBox) {
146 this.updateDataSeriesVisibility_(dataSeries, listItem, checkBox);
147 this.graphView_.repaint();
148 },
149
150 /**
151 * Adds the specified DataSeries to |dataSeries_|, and hooks up
152 * |listItemId|'s checkbox and color to correspond to the current state
153 * of the given DataSeries.
154 */
155 addDataSeries_: function(dataSeries, listItemId) {
156 this.dataSeries_.push(dataSeries);
157 var listItem = $(listItemId);
158 var checkBox = $(listItemId).querySelector('input');
159
160 // Make sure |listItem| is visible, and then use its color for the
161 // DataSource.
162 changeClassName(listItem, TimelineView.HIDDEN_CLASS, false);
163 dataSeries.setColor(getComputedStyle(listItem).color);
164
165 this.updateDataSeriesVisibility_(dataSeries, listItem, checkBox);
166 checkBox.onclick = this.dataSeriesClicked_.bind(this, dataSeries,
167 listItem, checkBox);
168 },
169
170 /**
171 * Recreate all DataSeries. Global constants must have been set before
172 * this is called.
173 */
174 createDataSeries_: function() {
175 this.graphRangeInitialized_ = false;
176 this.dataSeries_ = [];
177
178 this.addDataSeries_(new SourceCountDataSeries(
179 LogSourceType.SOCKET,
180 LogEventType.SOCKET_ALIVE),
181 TimelineView.OPEN_SOCKETS_ID);
182
183 this.addDataSeries_(new SocketsInUseDataSeries(),
184 TimelineView.IN_USE_SOCKETS_ID);
185
186 this.addDataSeries_(new SourceCountDataSeries(
187 LogSourceType.URL_REQUEST,
188 LogEventType.REQUEST_ALIVE),
189 TimelineView.URL_REQUESTS_ID);
190
191 this.addDataSeries_(new SourceCountDataSeries(
192 LogSourceType.HOST_RESOLVER_IMPL_REQUEST,
193 LogEventType.HOST_RESOLVER_IMPL_REQUEST),
194 TimelineView.DNS_REQUESTS_ID);
195
196 this.addDataSeries_(new NetworkTransferRateDataSeries(
197 LogEventType.SOCKET_BYTES_RECEIVED,
198 LogEventType.UDP_BYTES_RECEIVED),
199 TimelineView.BYTES_RECEIVED_ID);
200
201 this.addDataSeries_(new NetworkTransferRateDataSeries(
202 LogEventType.SOCKET_BYTES_SENT,
203 LogEventType.UDP_BYTES_SENT),
204 TimelineView.BYTES_SENT_ID);
205
206 this.addDataSeries_(new DiskCacheTransferRateDataSeries(),
207 TimelineView.DISK_CACHE_BYTES_READ_ID);
208
209 this.addDataSeries_(new DiskCacheTransferRateDataSeries(),
210 TimelineView.DISK_CACHE_BYTES_WRITTEN_ID);
211
212 this.graphView_.setDataSeries(this.dataSeries_);
213 },
214
215 /**
216 * When we receive the constants, create or recreate the DataSeries.
217 */
218 onReceivedConstants: function(constants) {
219 this.createDataSeries_();
220 },
221
222 /**
223 * When log entries are deleted, simpler to recreate the DataSeries, rather
224 * than clearing them.
225 */
226 onAllLogEntriesDeleted: function() {
227 this.graphRangeInitialized_ = false;
228 this.createDataSeries_();
229 },
230
231 onReceivedLogEntries: function(entries) {
232 // Pass each entry to every DataSeries, one at a time. Not having each
233 // data series get data directly from the SourceTracker saves us from
234 // having very un-Javascript-like destructors for when we load new,
235 // constants and slightly simplifies DataSeries objects.
236 for (var entry = 0; entry < entries.length; ++entry) {
237 for (var i = 0; i < this.dataSeries_.length; ++i)
238 this.dataSeries_[i].onReceivedLogEntry(entries[entry]);
239 }
240
241 // If this is the first non-empty set of entries we've received, or we're
242 // viewing a loaded log file, we will need to update the date range.
243 if (this.graphRangeInitialized_ && !MainView.isViewingLoadedLog())
244 return;
245 if (entries.length == 0)
246 return;
247
248 // Update the date range.
249 var startDate;
250 if (!this.graphRangeInitialized_) {
251 startDate = timeutil.convertTimeTicksToDate(entries[0].time);
252 } else {
253 startDate = this.graphView_.getStartDate();
254 }
255 var endDate =
256 timeutil.convertTimeTicksToDate(entries[entries.length - 1].time);
257 this.graphView_.setDateRange(startDate, endDate);
258 this.graphRangeInitialized_ = true;
259 }
260 };
261
262 return TimelineView;
263 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698