1<!DOCTYPE html> 2<!-- 3Copyright (c) 2013 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="stylesheet" href="/tracing/ui/tracks/process_track_base.css"> 9 10<link rel="import" href="/tracing/core/filter.html"> 11<link rel="import" href="/tracing/model/model_settings.html"> 12<link rel="import" href="/tracing/ui/base/dom_helpers.html"> 13<link rel="import" href="/tracing/ui/base/ui.html"> 14<link rel="import" href="/tracing/ui/tracks/container_track.html"> 15<link rel="import" href="/tracing/ui/tracks/counter_track.html"> 16<link rel="import" href="/tracing/ui/tracks/frame_track.html"> 17<link rel="import" href="/tracing/ui/tracks/object_instance_group_track.html"> 18<link rel="import" href="/tracing/ui/tracks/process_summary_track.html"> 19<link rel="import" href="/tracing/ui/tracks/spacing_track.html"> 20<link rel="import" href="/tracing/ui/tracks/thread_track.html"> 21 22<script> 23'use strict'; 24 25tr.exportTo('tr.ui.tracks', function() { 26 27 var ObjectSnapshotView = tr.ui.analysis.ObjectSnapshotView; 28 var ObjectInstanceView = tr.ui.analysis.ObjectInstanceView; 29 var SpacingTrack = tr.ui.tracks.SpacingTrack; 30 31 /** 32 * Visualizes a Process by building ThreadTracks and CounterTracks. 33 * @constructor 34 */ 35 var ProcessTrackBase = 36 tr.ui.b.define('process-track-base', tr.ui.tracks.ContainerTrack); 37 38 ProcessTrackBase.prototype = { 39 40 __proto__: tr.ui.tracks.ContainerTrack.prototype, 41 42 decorate: function(viewport) { 43 tr.ui.tracks.ContainerTrack.prototype.decorate.call(this, viewport); 44 45 this.processBase_ = undefined; 46 47 this.classList.add('process-track-base'); 48 this.classList.add('expanded'); 49 50 this.processNameEl_ = tr.ui.b.createSpan(); 51 this.processNameEl_.classList.add('process-track-name'); 52 53 this.headerEl_ = tr.ui.b.createDiv({className: 'process-track-header'}); 54 this.headerEl_.appendChild(this.processNameEl_); 55 this.headerEl_.addEventListener('click', this.onHeaderClick_.bind(this)); 56 57 this.appendChild(this.headerEl_); 58 }, 59 60 get processBase() { 61 return this.processBase_; 62 }, 63 64 set processBase(processBase) { 65 this.processBase_ = processBase; 66 67 if (this.processBase_) { 68 var modelSettings = new tr.model.ModelSettings(this.processBase_.model); 69 var defaultValue = this.processBase_.important; 70 this.expanded = modelSettings.getSettingFor( 71 this.processBase_, 'expanded', defaultValue); 72 } 73 74 this.updateContents_(); 75 }, 76 77 get expanded() { 78 return this.classList.contains('expanded'); 79 }, 80 81 set expanded(expanded) { 82 expanded = !!expanded; 83 84 if (this.expanded === expanded) 85 return; 86 87 this.classList.toggle('expanded'); 88 89 // Expanding and collapsing tracks is, essentially, growing and shrinking 90 // the viewport. We dispatch a change event to trigger any processing 91 // to happen. 92 this.viewport_.dispatchChangeEvent(); 93 94 if (!this.processBase_) 95 return; 96 97 var modelSettings = new tr.model.ModelSettings(this.processBase_.model); 98 modelSettings.setSettingFor(this.processBase_, 'expanded', expanded); 99 this.updateContents_(); 100 this.viewport.rebuildEventToTrackMap(); 101 this.viewport.rebuildContainerToTrackMap(); 102 }, 103 104 get hasVisibleContent() { 105 if (this.expanded) 106 return this.children.length > 1; 107 return true; 108 }, 109 110 onHeaderClick_: function(e) { 111 e.stopPropagation(); 112 e.preventDefault(); 113 this.expanded = !this.expanded; 114 }, 115 116 updateContents_: function() { 117 this.clearTracks_(); 118 119 if (!this.processBase_) 120 return; 121 122 this.processNameEl_.textContent = this.processBase_.userFriendlyName; 123 this.headerEl_.title = this.processBase_.userFriendlyDetails; 124 125 // Create the object instance tracks for this process. 126 this.willAppendTracks_(); 127 if (this.expanded) { 128 this.appendMemoryDumpTrack_(); 129 this.appendObjectInstanceTracks_(); 130 this.appendCounterTracks_(); 131 this.appendFrameTrack_(); 132 this.appendThreadTracks_(); 133 } else { 134 this.appendSummaryTrack_(); 135 } 136 this.didAppendTracks_(); 137 }, 138 139 addEventsToTrackMap: function(eventToTrackMap) { 140 this.tracks_.forEach(function(track) { 141 track.addEventsToTrackMap(eventToTrackMap); 142 }); 143 }, 144 145 willAppendTracks_: function() { 146 }, 147 148 didAppendTracks_: function() { 149 }, 150 151 appendMemoryDumpTrack_: function() { 152 }, 153 154 appendSummaryTrack_: function() { 155 var track = new tr.ui.tracks.ProcessSummaryTrack(this.viewport); 156 track.process = this.process; 157 if (!track.hasVisibleContent) 158 return; 159 this.appendChild(track); 160 // no spacing track, since this track only shown in collapsed state 161 }, 162 163 appendFrameTrack_: function() { 164 var frames = this.process ? this.process.frames : undefined; 165 if (!frames || !frames.length) 166 return; 167 168 var track = new tr.ui.tracks.FrameTrack(this.viewport); 169 track.frames = frames; 170 this.appendChild(track); 171 }, 172 173 appendObjectInstanceTracks_: function() { 174 var instancesByTypeName = 175 this.processBase_.objects.getAllInstancesByTypeName(); 176 var instanceTypeNames = tr.b.dictionaryKeys(instancesByTypeName); 177 instanceTypeNames.sort(); 178 179 var didAppendAtLeastOneTrack = false; 180 instanceTypeNames.forEach(function(typeName) { 181 var allInstances = instancesByTypeName[typeName]; 182 183 // If a object snapshot has a view it will be shown, 184 // unless the view asked for it to not be shown. 185 var instanceViewInfo = ObjectInstanceView.getTypeInfo( 186 undefined, typeName); 187 var snapshotViewInfo = ObjectSnapshotView.getTypeInfo( 188 undefined, typeName); 189 if (instanceViewInfo && !instanceViewInfo.metadata.showInTrackView) 190 instanceViewInfo = undefined; 191 if (snapshotViewInfo && !snapshotViewInfo.metadata.showInTrackView) 192 snapshotViewInfo = undefined; 193 var hasViewInfo = instanceViewInfo || snapshotViewInfo; 194 195 // There are some instances that don't merit their own track in 196 // the UI. Filter them out. 197 var visibleInstances = []; 198 for (var i = 0; i < allInstances.length; i++) { 199 var instance = allInstances[i]; 200 201 // Do not create tracks for instances that have no snapshots. 202 if (instance.snapshots.length === 0) 203 continue; 204 205 // Do not create tracks for instances that have implicit snapshots 206 // and don't have a view. 207 if (instance.hasImplicitSnapshots && !hasViewInfo) 208 continue; 209 210 visibleInstances.push(instance); 211 } 212 if (visibleInstances.length === 0) 213 return; 214 215 // Look up the constructor for this track, or use the default 216 // constructor if none exists. 217 var trackConstructor = 218 tr.ui.tracks.ObjectInstanceTrack.getConstructor( 219 undefined, typeName); 220 if (!trackConstructor) { 221 var snapshotViewInfo = ObjectSnapshotView.getTypeInfo( 222 undefined, typeName); 223 if (snapshotViewInfo && snapshotViewInfo.metadata.showInstances) { 224 trackConstructor = tr.ui.tracks.ObjectInstanceGroupTrack; 225 } else { 226 trackConstructor = tr.ui.tracks.ObjectInstanceTrack; 227 } 228 } 229 var track = new trackConstructor(this.viewport); 230 track.objectInstances = visibleInstances; 231 this.appendChild(track); 232 didAppendAtLeastOneTrack = true; 233 }, this); 234 if (didAppendAtLeastOneTrack) 235 this.appendChild(new SpacingTrack(this.viewport)); 236 }, 237 238 appendCounterTracks_: function() { 239 // Add counter tracks for this process. 240 var counters = tr.b.dictionaryValues(this.processBase.counters); 241 counters.sort(tr.model.Counter.compare); 242 243 // Create the counters for this process. 244 counters.forEach(function(counter) { 245 var track = new tr.ui.tracks.CounterTrack(this.viewport); 246 track.counter = counter; 247 this.appendChild(track); 248 this.appendChild(new SpacingTrack(this.viewport)); 249 }.bind(this)); 250 }, 251 252 appendThreadTracks_: function() { 253 // Get a sorted list of threads. 254 var threads = tr.b.dictionaryValues(this.processBase.threads); 255 threads.sort(tr.model.Thread.compare); 256 257 // Create the threads. 258 threads.forEach(function(thread) { 259 var track = new tr.ui.tracks.ThreadTrack(this.viewport); 260 track.thread = thread; 261 if (!track.hasVisibleContent) 262 return; 263 this.appendChild(track); 264 this.appendChild(new SpacingTrack(this.viewport)); 265 }.bind(this)); 266 } 267 }; 268 269 return { 270 ProcessTrackBase: ProcessTrackBase 271 }; 272}); 273</script> 274