Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / trace_viewer / about_tracing / profiling_view.js
1 // Copyright (c) 2013 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 'use strict';
6
7 /**
8  * @fileoverview ProfilingView glues the View control to
9  * TracingController.
10  */
11 tvcm.require('about_tracing.tracing_ui_client');
12 tvcm.require('tracing.timeline_view');
13 tvcm.require('tvcm.key_event_manager');
14 tvcm.require('tvcm.promise');
15 tvcm.require('tvcm.ui');
16 tvcm.require('tvcm.ui.info_bar');
17 tvcm.require('tvcm.ui.overlay');
18
19 tvcm.requireTemplate('about_tracing.profiling_view');
20 tvcm.require('about_tracing.features');
21
22 tvcm.exportTo('about_tracing', function() {
23   function readFile(file) {
24     return new Promise(function(resolver) {
25       var reader = new FileReader();
26       var filename = file.name;
27       reader.onload = function(data) {
28         resolver.resolve(data.target.result);
29       };
30       reader.onerror = function(err) {
31         resolver.reject(err);
32       }
33
34       var is_binary = /[.]gz$/.test(filename) || /[.]zip$/.test(filename);
35       if (is_binary)
36         reader.readAsArrayBuffer(file);
37       else
38         reader.readAsText(file);
39     });
40   }
41
42   /**
43    * ProfilingView
44    * @constructor
45    * @extends {HTMLUnknownElement}
46    */
47   var ProfilingView = tvcm.ui.define('x-profiling-view');
48
49   ProfilingView.prototype = {
50     __proto__: HTMLUnknownElement.prototype,
51
52     decorate: function(tracingRequestImpl) {
53       this.appendChild(tvcm.instantiateTemplate('#profiling-view-template'));
54
55       this.timelineView_ = this.querySelector('x-timeline-view');
56       this.infoBarGroup_ = this.querySelector('x-info-bar-group');
57
58       tvcm.ui.decorate(this.infoBarGroup_, tvcm.ui.InfoBarGroup);
59       tvcm.ui.decorate(this.timelineView_, tracing.TimelineView);
60
61       // Detach the buttons. We will reattach them to the timeline view.
62       // TODO(nduca): Make <timeline-view> have a <content select="x-buttons">
63       // that pulls in any buttons.
64       var buttons = this.querySelector('x-timeline-view-buttons');
65       buttons.parentElement.removeChild(buttons);
66       this.timelineView_.leftControls.appendChild(buttons);
67       this.initButtons_(buttons);
68
69       tvcm.KeyEventManager.instance.addListener(
70           'keypress', this.onKeypress_, this);
71
72       this.initDragAndDrop_();
73
74       this.tracingRequestImpl_ =
75           tracingRequestImpl || about_tracing.tracingRequest;
76       this.isRecording_ = false;
77       this.isMonitoring_ = false;
78       this.activeTrace_ = undefined;
79
80       window.onMonitoringStateChanged = function(is_monitoring) {
81         this.onMonitoringStateChanged_(is_monitoring);
82       }.bind(this);
83
84       this.getMonitoringStatus();
85     },
86
87     // Detach all document event listeners. Without this the tests can get
88     // confused as the element may still be listening when the next test runs.
89     detach_: function() {
90       this.detachDragAndDrop_();
91     },
92
93     get isRecording() {
94       return this.isRecording_;
95     },
96
97     get isMonitoring() {
98       return this.isMonitoring_;
99     },
100
101     set tracingRequestImpl(tracingRequestImpl) {
102       this.tracingRequestImpl_ = tracingRequestImpl;
103     },
104
105     beginRecording: function() {
106       if (this.isRecording_)
107         throw new Error('Already recording');
108       if (this.isMonitoring_)
109         throw new Error('Already monitoring');
110       this.isRecording_ = true;
111       var buttons = this.querySelector('x-timeline-view-buttons');
112       buttons.querySelector('#monitor-checkbox').disabled = true;
113       buttons.querySelector('#monitor-checkbox').checked = false;
114       var resultPromise = about_tracing.beginRecording(
115           this.tracingRequestImpl_);
116       resultPromise.then(
117           function(data) {
118             this.isRecording_ = false;
119             buttons.querySelector('#monitor-checkbox').disabled = false;
120             this.setActiveTrace('trace.json', data, false);
121           }.bind(this),
122           function(err) {
123             this.isRecording_ = false;
124             buttons.querySelector('#monitor-checkbox').disabled = false;
125             if (err instanceof about_tracing.UserCancelledError)
126               return;
127             tvcm.ui.Overlay.showError('Error while recording', err);
128           }.bind(this));
129       return resultPromise;
130     },
131
132     beginMonitoring: function() {
133       if (this.isRecording_)
134         throw new Error('Already recording');
135       if (this.isMonitoring_)
136         throw new Error('Already monitoring');
137       var buttons = this.querySelector('x-timeline-view-buttons');
138       var resultPromise =
139           about_tracing.beginMonitoring(this.tracingRequestImpl_);
140       resultPromise.then(
141           function() {
142           }.bind(this),
143           function(err) {
144             if (err instanceof about_tracing.UserCancelledError)
145               return;
146             tvcm.ui.Overlay.showError('Error while monitoring', err);
147           }.bind(this));
148       return resultPromise;
149     },
150
151     endMonitoring: function() {
152       if (this.isRecording_)
153         throw new Error('Already recording');
154       if (!this.isMonitoring_)
155         throw new Error('Monitoring is disabled');
156       var buttons = this.querySelector('x-timeline-view-buttons');
157       var resultPromise =
158           about_tracing.endMonitoring(this.tracingRequestImpl_);
159       resultPromise.then(
160           function() {
161           }.bind(this),
162           function(err) {
163             if (err instanceof about_tracing.UserCancelledError)
164               return;
165             tvcm.ui.Overlay.showError('Error while monitoring', err);
166           }.bind(this));
167       return resultPromise;
168     },
169
170     captureMonitoring: function() {
171       if (!this.isMonitoring_)
172         throw new Error('Monitoring is disabled');
173       var resultPromise =
174           about_tracing.captureMonitoring(this.tracingRequestImpl_);
175       resultPromise.then(
176           function(data) {
177             this.setActiveTrace('trace.json', data, true);
178           }.bind(this),
179           function(err) {
180             if (err instanceof about_tracing.UserCancelledError)
181               return;
182             tvcm.ui.Overlay.showError('Error while monitoring', err);
183           }.bind(this));
184       return resultPromise;
185     },
186
187     getMonitoringStatus: function() {
188       var resultPromise =
189           about_tracing.getMonitoringStatus(this.tracingRequestImpl_);
190       resultPromise.then(
191           function(isMonitoring, categoryFilter, useSystemTracing,
192                    useContinuousTracing, useSampling) {
193             this.onMonitoringStateChanged_(isMonitoring);
194           }.bind(this),
195           function(err) {
196             if (err instanceof about_tracing.UserCancelledError)
197               return;
198             tvcm.ui.Overlay.showError('Error while updating tracing states',
199                                       err);
200           }.bind(this));
201       return resultPromise;
202     },
203
204     onMonitoringStateChanged_: function(is_monitoring) {
205       this.isMonitoring_ = is_monitoring;
206       var buttons = this.querySelector('x-timeline-view-buttons');
207       buttons.querySelector('#record-button').disabled = is_monitoring;
208       buttons.querySelector('#capture-button').disabled = !is_monitoring;
209       buttons.querySelector('#monitor-checkbox').checked = is_monitoring;
210     },
211
212     onKeypress_: function(event) {
213       if (document.activeElement.nodeName === 'INPUT')
214         return;
215
216       if (!this.isRecording &&
217           event.keyCode === 'r'.charCodeAt(0)) {
218         this.beginRecording();
219         event.preventDefault();
220         event.stopPropagation();
221         return true;
222       }
223     },
224
225     get timelineView() {
226       return this.timelineView_;
227     },
228
229     ///////////////////////////////////////////////////////////////////////////
230
231     clearActiveTrace: function() {
232       this.saveButton_.disabled = true;
233       this.activeTrace_ = undefined;
234     },
235
236     setActiveTrace: function(filename, data) {
237       this.activeTrace_ = {
238         filename: filename,
239         data: data
240       };
241
242       this.infoBarGroup_.clearMessages();
243       this.saveButton_.disabled = false;
244       this.timelineView_.viewTitle = filename;
245
246       var m = new tracing.TraceModel();
247       var p = m.importTracesWithProgressDialog([data], true);
248       p.then(
249           function() {
250             this.timelineView_.model = m;
251           }.bind(this),
252           function(err) {
253             tvcm.ui.Overlay.showError('While importing: ', err);
254           }.bind(this));
255     },
256
257     ///////////////////////////////////////////////////////////////////////////
258
259     initButtons_: function(buttons) {
260       buttons.querySelector('#record-button').addEventListener(
261           'click', function() {
262             this.beginRecording();
263           }.bind(this));
264
265       buttons.querySelector('#monitor-checkbox').addEventListener(
266           'click', function() {
267             if (this.isMonitoring_)
268               this.endMonitoring();
269             else
270               this.beginMonitoring();
271           }.bind(this));
272
273       buttons.querySelector('#capture-button').addEventListener(
274           'click', function() {
275             this.captureMonitoring();
276           }.bind(this));
277       buttons.querySelector('#capture-button').disabled = true;
278
279       buttons.querySelector('#load-button').addEventListener(
280           'click', this.onLoadClicked_.bind(this));
281
282       this.saveButton_ = buttons.querySelector('#save-button');
283       this.saveButton_.addEventListener('click',
284                                         this.onSaveClicked_.bind(this));
285       this.saveButton_.disabled = true;
286     },
287
288     onSaveClicked_: function() {
289       // Create a blob URL from the binary array.
290       var blob = new Blob([this.activeTrace_.data],
291                           {type: 'application/octet-binary'});
292       var blobUrl = window.webkitURL.createObjectURL(blob);
293
294       // Create a link and click on it. BEST API EVAR!
295       var link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
296       link.href = blobUrl;
297       link.download = this.activeTrace_.filename;
298       link.click();
299     },
300
301     onLoadClicked_: function() {
302       var inputElement = document.createElement('input');
303       inputElement.type = 'file';
304       inputElement.multiple = false;
305
306       var changeFired = false;
307       inputElement.addEventListener(
308           'change',
309           function(e) {
310             if (changeFired)
311               return;
312             changeFired = true;
313
314             var file = inputElement.files[0];
315             readFile(file).then(
316                 function(data) {
317                   this.setActiveTrace(file.name, data);
318                 }.bind(this),
319                 function(err) {
320                   tvcm.ui.Overlay.showError('Error while loading file: ' + err);
321                 });
322           }.bind(this), false);
323       inputElement.click();
324     },
325
326     ///////////////////////////////////////////////////////////////////////////
327
328     initDragAndDrop_: function() {
329       this.dropHandler_ = this.dropHandler_.bind(this);
330       this.ignoreDragEvent_ = this.ignoreDragEvent_.bind(this);
331       document.addEventListener('dragstart', this.ignoreDragEvent_, false);
332       document.addEventListener('dragend', this.ignoreDragEvent_, false);
333       document.addEventListener('dragenter', this.ignoreDragEvent_, false);
334       document.addEventListener('dragleave', this.ignoreDragEvent_, false);
335       document.addEventListener('dragover', this.ignoreDragEvent_, false);
336       document.addEventListener('drop', this.dropHandler_, false);
337     },
338
339     detachDragAndDrop_: function() {
340       document.removeEventListener('dragstart', this.ignoreDragEvent_);
341       document.removeEventListener('dragend', this.ignoreDragEvent_);
342       document.removeEventListener('dragenter', this.ignoreDragEvent_);
343       document.removeEventListener('dragleave', this.ignoreDragEvent_);
344       document.removeEventListener('dragover', this.ignoreDragEvent_);
345       document.removeEventListener('drop', this.dropHandler_);
346     },
347
348     ignoreDragEvent_: function(e) {
349       e.preventDefault();
350       return false;
351     },
352
353     dropHandler_: function(e) {
354       if (this.isAnyDialogUp_)
355         return;
356
357       e.stopPropagation();
358       e.preventDefault();
359
360       var files = e.dataTransfer.files;
361       if (files.length !== 1) {
362         tvcm.ui.Overlay.showError('1 file supported at a time.');
363         return;
364       }
365
366       readFile(files[0]).then(
367           function(data) {
368             this.setActiveTrace(files[0].name, data);
369           }.bind(this),
370           function(err) {
371             tvcm.ui.Overlay.showError('Error while loading file: ' + err);
372           });
373       return false;
374     }
375   };
376
377   return {
378     ProfilingView: ProfilingView
379   };
380 });