blob: b9af833a89b3c1692b3c782b7e43dda4249f1244 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2013 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="stylesheet" href="/core/tracks/process_track_base.css">
<link rel="import" href="/core/tracks/container_track.html">
<link rel="import" href="/core/tracks/counter_track.html">
<link rel="import" href="/core/tracks/object_instance_group_track.html">
<link rel="import" href="/core/tracks/process_summary_track.html">
<link rel="import" href="/core/tracks/spacing_track.html">
<link rel="import" href="/core/tracks/thread_track.html">
<link rel="import" href="/core/trace_model/trace_model_settings.html">
<link rel="import" href="/core/filter.html">
<link rel="import" href="/base/ui.html">
<link rel="import" href="/base/ui/dom_helpers.html">
<script>
'use strict';
tv.exportTo('tv.c.tracks', function() {
var ObjectSnapshotView = tv.c.analysis.ObjectSnapshotView;
var ObjectInstanceView = tv.c.analysis.ObjectInstanceView;
var TraceModelSettings = tv.c.TraceModelSettings;
var SpacingTrack = tv.c.tracks.SpacingTrack;
/**
* Visualizes a Process by building ThreadTracks and CounterTracks.
* @constructor
*/
var ProcessTrackBase =
tv.b.ui.define('process-track-base', tv.c.tracks.ContainerTrack);
ProcessTrackBase.prototype = {
__proto__: tv.c.tracks.ContainerTrack.prototype,
decorate: function(viewport) {
tv.c.tracks.ContainerTrack.prototype.decorate.call(this, viewport);
this.processBase_ = undefined;
this.classList.add('process-track-base');
this.classList.add('expanded');
this.processNameEl_ = tv.b.ui.createSpan();
this.processNameEl_.classList.add('process-track-name');
this.headerEl_ = tv.b.ui.createDiv({className: 'process-track-header'});
this.headerEl_.appendChild(this.processNameEl_);
this.headerEl_.addEventListener('click', this.onHeaderClick_.bind(this));
this.appendChild(this.headerEl_);
},
get processBase() {
return this.processBase_;
},
set processBase(processBase) {
this.processBase_ = processBase;
if (this.processBase_) {
var modelSettings = new TraceModelSettings(this.processBase_.model);
var defaultValue;
if (this.processBase_.labels !== undefined &&
this.processBase_.labels.length == 1 &&
this.processBase_.labels[0] == 'chrome://tracing') {
defaultValue = false;
} else {
defaultValue = true;
}
this.expanded = modelSettings.getSettingFor(
this.processBase_, 'expanded', defaultValue);
}
this.updateContents_();
},
get expanded() {
return this.classList.contains('expanded');
},
set expanded(expanded) {
expanded = !!expanded;
if (this.expanded === expanded)
return;
this.classList.toggle('expanded');
// Expanding and collapsing tracks is, essentially, growing and shrinking
// the viewport. We dispatch a change event to trigger any processing
// to happen.
this.viewport_.dispatchChangeEvent();
if (!this.processBase_)
return;
var modelSettings = new TraceModelSettings(this.processBase_.model);
modelSettings.setSettingFor(this.processBase_, 'expanded', expanded);
},
get hasVisibleContent() {
if (this.expanded)
return this.children.length > 1;
return true;
},
onHeaderClick_: function(e) {
e.stopPropagation();
e.preventDefault();
this.expanded = !this.expanded;
},
updateContents_: function() {
this.tracks_.forEach(function(track) {
this.removeChild(track);
}, this);
if (!this.processBase_)
return;
this.processNameEl_.textContent = this.processBase_.userFriendlyName;
this.headerEl_.title = this.processBase_.userFriendlyDetails;
// Create the object instance tracks for this process.
this.willAppendTracks_();
this.appendSummaryTrack_();
this.appendObjectInstanceTracks_();
this.appendCounterTracks_();
this.appendThreadTracks_();
this.didAppendTracks_();
},
addEventsToTrackMap: function(eventToTrackMap) {
this.tracks_.forEach(function(track) {
track.addEventsToTrackMap(eventToTrackMap);
});
},
willAppendTracks_: function() {
},
didAppendTracks_: function() {
},
appendSummaryTrack_: function() {
var track = new tv.c.tracks.ProcessSummaryTrack(this.viewport);
track.process = this.process;
if (!track.hasVisibleContent)
return;
this.appendChild(track);
this.appendChild(new SpacingTrack(this.viewport));
},
appendObjectInstanceTracks_: function() {
var instancesByTypeName =
this.processBase_.objects.getAllInstancesByTypeName();
var instanceTypeNames = tv.b.dictionaryKeys(instancesByTypeName);
instanceTypeNames.sort();
var didAppendAtLeastOneTrack = false;
instanceTypeNames.forEach(function(typeName) {
var allInstances = instancesByTypeName[typeName];
// If a object snapshot has a view it will be shown,
// unless the view asked for it to not be shown.
var instanceViewInfo = ObjectInstanceView.getTypeInfo(
undefined, typeName);
var snapshotViewInfo = ObjectSnapshotView.getTypeInfo(
undefined, typeName);
if (instanceViewInfo && !instanceViewInfo.metadata.showInTrackView)
instanceViewInfo = undefined;
if (snapshotViewInfo && !snapshotViewInfo.metadata.showInTrackView)
snapshotViewInfo = undefined;
var hasViewInfo = instanceViewInfo || snapshotViewInfo;
// There are some instances that don't merit their own track in
// the UI. Filter them out.
var visibleInstances = [];
for (var i = 0; i < allInstances.length; i++) {
var instance = allInstances[i];
// Do not create tracks for instances that have no snapshots.
if (instance.snapshots.length === 0)
continue;
// Do not create tracks for instances that have implicit snapshots
// and don't have a view.
if (instance.hasImplicitSnapshots && !hasViewInfo)
continue;
visibleInstances.push(instance);
}
if (visibleInstances.length === 0)
return;
// Look up the constructor for this track, or use the default
// constructor if none exists.
var trackConstructor =
tv.c.tracks.ObjectInstanceTrack.getConstructor(
undefined, typeName);
if (!trackConstructor) {
var snapshotViewInfo = ObjectSnapshotView.getTypeInfo(
undefined, typeName);
if (snapshotViewInfo && snapshotViewInfo.metadata.showInstances) {
trackConstructor = tv.c.tracks.ObjectInstanceGroupTrack;
} else {
trackConstructor = tv.c.tracks.ObjectInstanceTrack;
}
}
var track = new trackConstructor(this.viewport);
track.objectInstances = visibleInstances;
this.appendChild(track);
didAppendAtLeastOneTrack = true;
}, this);
if (didAppendAtLeastOneTrack)
this.appendChild(new SpacingTrack(this.viewport));
},
appendCounterTracks_: function() {
// Add counter tracks for this process.
var counters = tv.b.dictionaryValues(this.processBase.counters);
counters.sort(tv.c.trace_model.Counter.compare);
// Create the counters for this process.
counters.forEach(function(counter) {
var track = new tv.c.tracks.CounterTrack(this.viewport);
track.counter = counter;
this.appendChild(track);
this.appendChild(new SpacingTrack(this.viewport));
}.bind(this));
},
appendThreadTracks_: function() {
// Get a sorted list of threads.
var threads = tv.b.dictionaryValues(this.processBase.threads);
threads.sort(tv.c.trace_model.Thread.compare);
// Create the threads.
threads.forEach(function(thread) {
var track = new tv.c.tracks.ThreadTrack(this.viewport);
track.thread = thread;
if (!track.hasVisibleContent)
return;
this.appendChild(track);
this.appendChild(new SpacingTrack(this.viewport));
}.bind(this));
}
};
return {
ProcessTrackBase: ProcessTrackBase
};
});
</script>