1 // Copyright 2014 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.
5 <include src
="../../../../third_party/polymer_legacy/platform/platform.js">
6 <include src
="../../../../third_party/polymer_legacy/polymer/polymer.js">
9 * Formats size to a human readable form.
10 * @param {number} size Size in bytes.
11 * @return {string} Output string in a human-readable format.
13 function formatSizeCommon(size
) {
16 if (size
< 1024 * 1024)
17 return Math
.round(size
/ 1024) + ' KB';
18 return Math
.round(size
/ 1024 / 1024) + ' MB';
21 // Defines the file-systems element.
22 Polymer('file-systems', {
24 * Called when the element is created.
30 * Selects an active file system from the list.
31 * @param {Event} event Event.
32 * @param {number} detail Detail.
33 * @param {HTMLElement} sender Sender.
35 rowClicked: function(event
, detail
, sender
) {
36 var requestEventsNode
= document
.querySelector('#request-events');
37 requestEventsNode
.hidden
= false;
38 requestEventsNode
.model
= [];
40 var requestTimelineNode
= document
.querySelector('#request-timeline');
41 requestTimelineNode
.hidden
= false;
42 requestTimelineNode
.model
= [];
44 chrome
.send('selectFileSystem', [sender
.dataset
.extensionId
,
49 * List of provided file system information maps.
50 * @type {Array.<Object>}
55 // Defines the request-log element.
56 Polymer('request-events', {
58 * Called when the element is created.
64 * Formats time to a hh:mm:ss.xxxx format.
65 * @param {Date} time Input time.
66 * @return {string} Output string in a human-readable format.
68 formatTime: function(time
) {
69 return ('0' + time
.getHours()).slice(-2) + ':' +
70 ('0' + time
.getMinutes()).slice(-2) + ':' +
71 ('0' + time
.getSeconds()).slice(-2) + '.' +
72 ('000' + time
.getMilliseconds()).slice(-3);
76 * Formats size to a human readable form.
77 * @param {number} size Size in bytes.
78 * @return {string} Output string in a human-readable format.
80 formatSize: function(size
) {
81 return formatSizeCommon(size
);
85 * Formats a boolean value to human-readable form.
86 * @param {boolean=} opt_hasMore Input value.
87 * @return {string} Output string in a human-readable format.
89 formatHasMore: function(opt_hasMore
) {
90 if (opt_hasMore
== undefined)
93 return opt_hasMore
? 'HAS_MORE' : 'LAST';
97 * Formats execution time to human-readable form.
98 * @param {boolean=} opt_executionTime Input value.
99 * @return {string} Output string in a human-readable format.
101 formatExecutionTime: function(opt_executionTime
) {
102 if (opt_executionTime
== undefined)
105 return opt_executionTime
+ ' ms';
110 * @type {Array.<Object>}
115 // Defines the request-timeline element.
116 Polymer('request-timeline', {
118 * Step for zoomin in and out.
125 * Height of each row in the chart in pixels.
132 * Observes changes in the model.
133 * @type {Object.<string, string>}
136 'model.length': 'chartUpdate'
140 * Called when the element is created.
143 // Update active requests in the background for nice animation.
144 var activeUpdateAnimation = function() {
146 requestAnimationFrame(activeUpdateAnimation
);
148 activeUpdateAnimation();
152 * Formats size to a human readable form.
153 * @param {number} size Size in bytes.
154 * @return {string} Output string in a human-readable format.
156 formatSize: function(size
) {
157 return formatSizeCommon(size
);
161 * Zooms in the timeline.
162 * @param {Event} event Event.
163 * @param {number} detail Detail.
164 * @param {HTMLElement} sender Sender.
166 zoomInClicked: function(event
, detail
, sender
) {
167 this.scale
*= this.SCALE_STEP
;
171 * Zooms out the timeline.
172 * @param {Event} event Event.
173 * @param {number} detail Detail.
174 * @param {HTMLElement} sender Sender.
176 zoomOutClicked: function(event
, detail
, sender
) {
177 this.scale
/= this.SCALE_STEP
;
181 * Selects or deselects an element on the timeline.
182 * @param {Event} event Event.
183 * @param {number} detail Detail.
184 * @param {HTMLElement} sender Sender.
186 elementClicked: function(event
, detail
, sender
) {
187 if (sender
.dataset
.id
in this.selected
) {
188 delete this.selected
[sender
.dataset
.id
];
189 sender
.classList
.remove('selected');
191 this.selected
[sender
.dataset
.id
] = true;
192 sender
.classList
.add('selected');
195 var requestEventsNode
= document
.querySelector('#request-events');
196 requestEventsNode
.hidden
= false;
198 requestEventsNode
.model
= [];
199 for (var i
= 0; i
< this.model
.length
; i
++) {
200 if (this.model
[i
].id
in this.selected
)
201 requestEventsNode
.model
.push(this.model
[i
]);
206 * Updates chart elements of active requests, so they grow with time.
208 activeUpdate: function() {
209 if (Object
.keys(this.active
).length
== 0)
212 for (var id
in this.active
) {
213 var index
= this.active
[id
];
214 this.chart
[index
].length
= Date
.now() - this.chart
[index
].time
;
219 * Generates <code>chart</code> from the new <code>model</code> value.
221 chartUpdate: function(oldLength
, newLength
) {
222 // If the new value is empty, then clear the model.
227 this.timeStart
= null;
228 this.idleStart
= null;
234 // Only adding new entries to the model is supported (or clearing).
235 console
.assert(newLength
>= oldLength
);
237 for (var i
= oldLength
; i
< newLength
; i
++) {
238 var event
= this.model
[i
];
239 switch (event
.eventType
) {
241 // If this is the first creation event in the chart, then store its
242 // time as beginning time of the chart.
244 this.timeStart
= event
.time
;
246 // If this event terminates idling, then add the idling time to total
247 // idling time. This is used to avoid gaps in the chart while idling.
248 if (Object
.keys(this.active
).length
== 0 && this.idleStart
)
249 this.idleTotal
+= event
.time
.getTime() - this.idleStart
.getTime();
251 // Find the appropriate row for this chart element.
254 // Add to this row only if there is enough space, and if the row
255 // is of the same type.
256 var addToRow
= (rowIndex
>= this.rows
.length
) ||
257 (this.rows
[rowIndex
].time
.getTime() <= event
.time
.getTime() &&
258 !this.rows
[rowIndex
].active
&&
259 (this.rows
[rowIndex
].requestType
== event
.requestType
));
263 index
: this.chart
.length
,
268 requestType
: event
.requestType
,
269 left
: event
.time
- this.timeStart
- this.idleTotal
,
274 this.rows
[rowIndex
] = {
275 requestType
: event
.requestType
,
280 this.active
[event
.id
] = this.chart
.length
- 1;
290 if (!(event
.id
in this.active
))
292 var chartIndex
= this.active
[event
.id
];
293 this.chart
[chartIndex
].state
= event
.eventType
;
294 this.chart
[chartIndex
].executionTime
= event
.executionTime
;
295 this.chart
[chartIndex
].valueSize
= event
.valueSize
;
296 this.chart
[chartIndex
].modelIndexes
.push(i
);
300 if (!(event
.id
in this.active
))
303 var chartIndex
= this.active
[event
.id
];
304 this.chart
[chartIndex
].length
=
305 event
.time
- this.chart
[chartIndex
].time
;
306 this.chart
[chartIndex
].modelIndexes
.push(i
);
307 this.rows
[this.chart
[chartIndex
].row
].time
= event
.time
;
308 this.rows
[this.chart
[chartIndex
].row
].active
= false;
309 delete this.active
[event
.id
];
311 // If this was the last active request, then idling starts.
312 if (Object
.keys(this.active
).length
== 0)
313 this.idleStart
= event
.time
;
320 * Map of selected requests.
321 * @type {Object.<number, boolean>}
326 * Map of requests which has started, but are not completed yet, from
327 * a request id to the chart element index.
328 * @type {Object.<number, number>}}
333 * List of chart elements, calculated from the model.
334 * @type {Array.<Object>}
339 * List of rows in the chart, with the last endTime value on it.
340 * @type {Array.<Object>}
345 * Scale of the chart.
351 * Time of the first created request.
357 * Time of the last idling started.
363 * Total idling time since chart generation started. Used to avoid
364 * generating gaps in the chart when there is no activity. In milliseconds.
370 * List of requests information maps.
371 * @type {Array.<Object>}
377 * Updates the mounted file system list.
378 * @param {Array.<Object>} fileSystems Array containing provided file system
381 function updateFileSystems(fileSystems
) {
382 var fileSystemsNode
= document
.querySelector('#file-systems');
383 fileSystemsNode
.model
= fileSystems
;
387 * Called when a request is created.
388 * @param {Object} event Event.
390 function onRequestEvent(event
) {
391 event
.time
= new Date(event
.time
); // Convert to a real Date object.
392 var requestTimelineNode
= document
.querySelector('#request-timeline');
393 requestTimelineNode
.model
.push(event
);
396 document
.addEventListener('DOMContentLoaded', function() {
397 var context
= document
.getCSSCanvasContext('2d', 'dashedPattern', 4, 4);
399 context
.strokeStyle
= '#ffffff';
400 context
.moveTo(0, 0);
401 context
.lineTo(4, 4);
404 chrome
.send('updateFileSystems');
406 // Refresh periodically.
407 setInterval(function() {
408 chrome
.send('updateFileSystems');