| <!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/frame_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 = this.processBase_.important; |
| 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); |
| this.updateContents_(); |
| this.viewport.rebuildEventToTrackMap(); |
| this.viewport.rebuildContainerToTrackMap(); |
| }, |
| |
| 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_(); |
| if (this.expanded) { |
| this.appendMemoryDumpTrack_(); |
| this.appendObjectInstanceTracks_(); |
| this.appendCounterTracks_(); |
| this.appendFrameTrack_(); |
| this.appendThreadTracks_(); |
| } else { |
| this.appendSummaryTrack_(); |
| } |
| this.didAppendTracks_(); |
| }, |
| |
| addEventsToTrackMap: function(eventToTrackMap) { |
| this.tracks_.forEach(function(track) { |
| track.addEventsToTrackMap(eventToTrackMap); |
| }); |
| }, |
| |
| willAppendTracks_: function() { |
| }, |
| |
| didAppendTracks_: function() { |
| }, |
| |
| appendMemoryDumpTrack_: function() { |
| }, |
| |
| appendSummaryTrack_: function() { |
| var track = new tv.c.tracks.ProcessSummaryTrack(this.viewport); |
| track.process = this.process; |
| if (!track.hasVisibleContent) |
| return; |
| this.appendChild(track); |
| // no spacing track, since this track only shown in collapsed state |
| }, |
| |
| appendFrameTrack_: function() { |
| var frames = this.process ? this.process.frames : undefined; |
| if (!frames || !frames.length) |
| return; |
| |
| var track = new tv.c.tracks.FrameTrack(this.viewport); |
| track.frames = frames; |
| this.appendChild(track); |
| this.backgroundProvider = track; |
| }, |
| |
| 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> |