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

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: Update comments 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 DataSeries its GraphView displays.
9 */
10 var TimelineView = (function() {
11 'use strict';
12
13 // We inherit from DivView.
eroman 2011/11/16 04:03:46 comment differs from reality
mmenke 2011/11/16 18:39:35 Done.
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, shared with the graph. The TimelineView updates
40 // their state, the graph reads their state.
41 this.dataSeries_ = [];
42
43 // DataSeries depend on some of the global constants, so they're only
44 // created when constants are received. We also use this message to
45 // recreate DataSeries when log files are being loaded.
46 g_browser.addConstantsObserver(this);
47
48 // We observe the log entries to determine the range of the graph.
49 // We initialize the range to initially include all events, but after
50 // that, we only update it to be the current time, on a timer.
51 g_browser.sourceTracker.addLogEntryObserver(this);
52 this.graphRangeInitialized_ = false;
53 }
54
55 // ID for special HTML element in category_tabs.html
56 TimelineView.TAB_HANDLE_ID = 'tab-handle-timeline';
57
58 // IDs for special HTML elements in timeline_view.html
59 TimelineView.GRAPH_DIV_ID = 'timeline-view-graph-div';
60 TimelineView.GRAPH_CANVAS_ID = 'timeline-view-graph-canvas';
61 TimelineView.VERTICAL_SPLITTER_ID = 'timeline-view-vertical-splitter';
62 TimelineView.SELECTION_DIV_ID = 'timeline-view-selection-div';
63 TimelineView.SCROLLBAR_DIV_ID = 'timeline-view-scrollbar-div';
64 TimelineView.SCROLLBAR_INNER_DIV_ID = 'timeline-view-scrollbar-inner-div';
65
66 TimelineView.OPEN_SOCKETS_ID = 'timeline-view-open-sockets';
67 TimelineView.IN_USE_SOCKETS_ID = 'timeline-view-in-use-sockets';
68 TimelineView.URL_REQUESTS_ID = 'timeline-view-url-requests';
69 TimelineView.DNS_REQUESTS_ID = 'timeline-view-dns-requests';
70 TimelineView.BYTES_RECEIVED_ID = 'timeline-view-bytes-received';
71 TimelineView.BYTES_SENT_ID = 'timeline-view-bytes-sent';
72 TimelineView.DISK_CACHE_BYTES_READ_ID =
73 'timeline-view-disk-cache-bytes-read';
74 TimelineView.DISK_CACHE_BYTES_WRITTEN_ID =
75 'timeline-view-disk-cache-bytes-written';
76
77 // Class used for hiding the colored squares next to each label name.
78 TimelineView.HIDDEN_CLASS = 'timeline-view-hidden';
79
80 cr.addSingletonGetter(TimelineView);
81
82 // Frequency with which we increase the end date when actively capturing
83 // events.
84 var UPDATE_INTERVAL_MS = 2000;
85
86 TimelineView.prototype = {
87 // Inherit the superclass's methods.
88 __proto__: superClass.prototype,
89
90 setGeometry: function(left, top, width, height) {
91 superClass.prototype.setGeometry.call(this, left, top, width, height);
92 },
93
94 show: function(isVisible) {
95 superClass.prototype.show.call(this, isVisible);
96 // If we're hidden or viewing a log file, refresh the graph and make sure
97 // no interval is running.
98 if (!isVisible || MainView.isViewingLoadedLog()) {
99 this.setUpdateEndDateInterval_(0);
100 return;
101 }
102
103 // Otherwise, update the visible range on a loop.
104 this.setUpdateEndDateInterval_(UPDATE_INTERVAL_MS);
105 this.updateEndDate_();
106 },
107
108 /**
109 * Start calling the GraphView's updateEndDate function every |intervalMs|
110 * milliseconds. If |intervalMs| is 0, stops calling the function.
111 */
112 setUpdateEndDateInterval_: function(intervalMs) {
113 if (this.updateIntervalId_ !== null) {
114 window.clearInterval(this.updateIntervalId_);
115 this.updateIntervalId_ = null;
116 }
117 if (intervalMs > 0) {
118 this.updateIntervalId_ =
119 window.setInterval(this.updateEndDate_.bind(this), intervalMs);
120 }
121 },
122
123 updateEndDate_: function() {
124 this.graphView_.updateEndDate();
125 },
126
127 onLoadLogFinish: function(data) {
128 this.setUpdateEndDateInterval_(0);
129 return true;
130 },
131
132 /**
133 * Updates the visibility state of |dataSeries| to correspond to the
134 * current checked state of |checkBox|. Also updates the class of
135 * |listItem| based on the new visibility state.
136 */
137 updateDataSeriesVisibility_: function(dataSeries, listItem, checkBox) {
138 dataSeries.show(checkBox.checked);
139 changeClassName(listItem, TimelineView.HIDDEN_CLASS, !checkBox.checked);
140 },
141
142 dataSeriesClicked_: function(dataSeries, listItem, checkBox) {
143 this.updateDataSeriesVisibility_(dataSeries, listItem, checkBox);
144 this.graphView_.repaint();
145 },
146
147 /**
148 * Adds the specified DataSeries to |dataSeries_|, and hooks up
149 * |listItemId|'s checkbox and color to correspond to the current state
150 * of the given DataSeries.
151 */
152 addDataSeries_: function(dataSeries, listItemId) {
153 this.dataSeries_.push(dataSeries);
154 var listItem = $(listItemId);
155 var checkBox = $(listItemId).querySelector('input');
156
157 // Make sure |listItem| is visible, and then use its color for the
158 // DataSource.
159 changeClassName(listItem, TimelineView.HIDDEN_CLASS, false);
160 dataSeries.setColor(getComputedStyle(listItem).color);
161
162 this.updateDataSeriesVisibility_(dataSeries, listItem, checkBox);
163 checkBox.onclick = this.dataSeriesClicked_.bind(this, dataSeries,
164 listItem, checkBox);
165 },
166
167 /**
168 * Recreate all data series. Global constants must be set before this
169 * is called.
170 */
171 createDataSeries_: function() {
172 this.graphRangeInitialized_ = false;
173 this.dataSeries_ = [];
174
175 this.addDataSeries_(new SourceCountDataSeries(
176 LogSourceType.SOCKET,
177 LogEventType.SOCKET_ALIVE),
178 TimelineView.OPEN_SOCKETS_ID);
179
180 this.addDataSeries_(new SocketsInUseDataSeries(),
181 TimelineView.IN_USE_SOCKETS_ID);
182
183 this.addDataSeries_(new SourceCountDataSeries(
184 LogSourceType.URL_REQUEST,
185 LogEventType.REQUEST_ALIVE),
186 TimelineView.URL_REQUESTS_ID);
187
188 this.addDataSeries_(new SourceCountDataSeries(
189 LogSourceType.HOST_RESOLVER_IMPL_REQUEST,
190 LogEventType.HOST_RESOLVER_IMPL_REQUEST),
191 TimelineView.DNS_REQUESTS_ID);
192
193 this.addDataSeries_(new NetworkTransferRateDataSeries(
194 LogEventType.SOCKET_BYTES_RECEIVED,
195 LogEventType.UDP_BYTES_RECEIVED),
196 TimelineView.BYTES_RECEIVED_ID);
197
198 this.addDataSeries_(new NetworkTransferRateDataSeries(
199 LogEventType.SOCKET_BYTES_SENT,
200 LogEventType.UDP_BYTES_SENT),
201 TimelineView.BYTES_SENT_ID);
202
203 this.addDataSeries_(new DiskCacheTransferRateDataSeries(),
204 TimelineView.DISK_CACHE_BYTES_READ_ID);
205
206 this.addDataSeries_(new DiskCacheTransferRateDataSeries(),
207 TimelineView.DISK_CACHE_BYTES_WRITTEN_ID);
208
209 this.graphView_.setDataSeries(this.dataSeries_);
210 },
211
212 /**
213 * When we receive the constants, create or recreate the DataSeries.
214 */
215 onReceivedConstants: function(constants) {
216 this.createDataSeries_();
217 },
218
219 /**
220 * When log entries are deleted, simpler to recreate the DataSeries, rather
221 * than clearing them.
222 */
223 onAllLogEntriesDeleted: function() {
224 this.graphRangeInitialized_ = false;
225 this.createDataSeries_();
226 },
227
228 onReceivedLogEntries: function(entries) {
229 // Pass each entry to every DataSeries, one at a time. Not having each
230 // DataSeries get data directly from the SourceTracker saves us from
231 // having very un-Javascript-like destructors when we recreate them,
232 // and slightly simplifies DataSeries objects.
233 for (var entry = 0; entry < entries.length; ++entry) {
234 for (var i = 0; i < this.dataSeries_.length; ++i)
235 this.dataSeries_[i].onReceivedLogEntry(entries[entry]);
236 }
237
238 if (this.graphRangeInitialized_ || entries.length == 0)
239 return;
240 var startDate = timeutil.convertTimeTicksToDate(entries[0].time);
241 var endDate =
242 timeutil.convertTimeTicksToDate(entries[entries.length - 1].time);
243 this.graphView_.setDateRange(startDate, endDate);
244 this.graphRangeInitialized_ = true;
245 }
246 };
247
248 return TimelineView;
249 })();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698