1 // Copyright (c) 2012 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 TimelineView control to 9 * TracingController. 10 */ 11 base.requireStylesheet('profiling_view'); 12 base.require('timeline_view'); 13 base.require('tracing_controller'); 14 base.exportTo('tracing', function() { 15 /** 16 * ProfilingView 17 * @constructor 18 * @extends {HTMLDivElement} 19 */ 20 var ProfilingView = base.ui.define('div'); 21 22 ProfilingView.prototype = { 23 __proto__: HTMLDivElement.prototype, 24 25 traceEvents_: [], 26 systemTraceEvents_: [], 27 28 decorate: function() { 29 this.classList.add('profiling-view'); 30 31 // make the <list>/add/save/record element 32 this.recordBn_ = document.createElement('button'); 33 this.recordBn_.className = 'record'; 34 this.recordBn_.textContent = 'Record'; 35 this.recordBn_.addEventListener('click', this.onRecord_.bind(this)); 36 37 this.saveBn_ = document.createElement('button'); 38 this.saveBn_.textContent = 'Save'; 39 this.saveBn_.addEventListener('click', this.onSave_.bind(this)); 40 41 this.loadBn_ = document.createElement('button'); 42 this.loadBn_.textContent = 'Load'; 43 this.loadBn_.addEventListener('click', this.onLoad_.bind(this)); 44 45 this.systemTracingBn_ = document.createElement('input'); 46 this.systemTracingBn_.type = 'checkbox'; 47 this.systemTracingBn_.checked = false; 48 49 this.systemTracingLabelEl_ = document.createElement('label'); 50 this.systemTracingLabelEl_.textContent = 'System events'; 51 this.systemTracingLabelEl_.appendChild(this.systemTracingBn_); 52 this.systemTracingLabelEl_.style.display = 'none'; 53 this.systemTracingLabelEl_.style.marginLeft = '16px'; 54 55 this.timelineView_ = new tracing.TimelineView(); 56 this.timelineView_.leftControls.appendChild(this.recordBn_); 57 this.timelineView_.leftControls.appendChild(this.saveBn_); 58 this.timelineView_.leftControls.appendChild(this.loadBn_); 59 this.timelineView_.leftControls.appendChild(this.systemTracingLabelEl_); 60 61 this.appendChild(this.timelineView_); 62 63 document.addEventListener('keypress', this.onKeypress_.bind(this)); 64 65 this.refresh_(); 66 }, 67 68 didSetTracingController_: function(value, oldValue) { 69 if (oldValue) 70 throw new Error('Can only set tracing controller once.'); 71 72 if (this.tracingController_.supportsSystemTracing) { 73 this.systemTracingLabelEl_.style.display = 'block'; 74 this.systemTracingBn_.checked = true; 75 } else { 76 this.systemTracingLabelEl_.style.display = 'none'; 77 } 78 79 this.refresh_(); 80 }, 81 82 refresh_: function() { 83 if (!this.tracingController_) 84 return; 85 86 var traceEvents = this.tracingController_.traceEvents; 87 var hasEvents = traceEvents && traceEvents.length; 88 89 this.saveBn_.disabled = !hasEvents; 90 91 if (!hasEvents) return; 92 93 var traces = [traceEvents]; 94 if (this.tracingController_.systemTraceEvents.length) 95 traces.push(this.tracingController_.systemTraceEvents); 96 97 var m = new tracing.TimelineModel(); 98 m.importTraces(traces, true); 99 this.timelineView_.model = m; 100 }, 101 102 onKeypress_: function(event) { 103 if (event.keyCode == 114 && !this.tracingController_.isTracingEnabled && 104 document.activeElement.nodeName != 'INPUT') { 105 this.onRecord_(); 106 } 107 }, 108 109 get timelineView() { 110 return this.timelineView_; 111 }, 112 113 /////////////////////////////////////////////////////////////////////////// 114 115 onRecord_: function() { 116 var that = this; 117 var tc = this.tracingController_; 118 tc.beginTracing(this.systemTracingBn_.checked); 119 function response() { 120 that.refresh_(); 121 setTimeout(function() { 122 tc.removeEventListener('traceEnded', response); 123 }, 0); 124 } 125 tc.addEventListener('traceEnded', response); 126 }, 127 128 /////////////////////////////////////////////////////////////////////////// 129 130 onSave_: function() { 131 this.overlayEl_ = new tracing.Overlay(); 132 this.overlayEl_.className = 'profiling-overlay'; 133 134 var labelEl = document.createElement('div'); 135 labelEl.className = 'label'; 136 labelEl.textContent = 'Saving...'; 137 this.overlayEl_.appendChild(labelEl); 138 this.overlayEl_.visible = true; 139 140 var that = this; 141 var tc = this.tracingController_; 142 function response() { 143 that.overlayEl_.visible = false; 144 that.overlayEl_ = undefined; 145 setTimeout(function() { 146 tc.removeEventListener('saveTraceFileComplete', response); 147 tc.removeEventListener('saveTraceFileCanceled', response); 148 }, 0); 149 } 150 tc.addEventListener('saveTraceFileComplete', response); 151 tc.addEventListener('saveTraceFileCanceled', response); 152 tc.beginSaveTraceFile(); 153 }, 154 155 /////////////////////////////////////////////////////////////////////////// 156 157 onLoad_: function() { 158 this.overlayEl_ = new tracing.Overlay(); 159 this.overlayEl_.className = 'profiling-overlay'; 160 161 var labelEl = document.createElement('div'); 162 labelEl.className = 'label'; 163 labelEl.textContent = 'Loading...'; 164 this.overlayEl_.appendChild(labelEl); 165 this.overlayEl_.visible = true; 166 167 var that = this; 168 var tc = this.tracingController_; 169 this.tracingController_.beginLoadTraceFile(); 170 function response(e) { 171 that.overlayEl_.visible = false; 172 that.overlayEl_ = undefined; 173 if (e.type == 'loadTraceFileComplete') 174 that.refresh_(); 175 setTimeout(function() { 176 tc.removeEventListener('loadTraceFileComplete', response); 177 tc.removeEventListener('loadTraceFileCanceled', response); 178 }, 0); 179 } 180 181 tc.addEventListener('loadTraceFileComplete', response); 182 tc.addEventListener('loadTraceFileCanceled', response); 183 } 184 }; 185 186 base.defineProperty(ProfilingView, 'tracingController', base.PropertyKind.JS, 187 ProfilingView.prototype.didSetTracingController_); 188 189 return { 190 ProfilingView: ProfilingView 191 }; 192 }); 193