Chromium Code Reviews| Index: Source/devtools/front_end/timeline/TimelinePanel.js |
| diff --git a/Source/devtools/front_end/timeline/TimelinePanel.js b/Source/devtools/front_end/timeline/TimelinePanel.js |
| index 3123606d92cfc4857d6b5e4f98fb39212ac44ef6..6afe501fc012420e0c13d6916b9a00bac626aff6 100644 |
| --- a/Source/devtools/front_end/timeline/TimelinePanel.js |
| +++ b/Source/devtools/front_end/timeline/TimelinePanel.js |
| @@ -270,6 +270,13 @@ WebInspector.TimelinePanel.prototype = { |
| return this._lazyPaintProfilerView; |
| }, |
| + _causesView: function() |
| + { |
| + if (!this._lazyCausesView) |
| + this._lazyCausesView = new WebInspector.TimelineCausesView(); |
| + return this._lazyCausesView; |
| + }, |
| + |
| /** |
| * @param {!WebInspector.TimelineModeView} modeView |
| */ |
| @@ -347,11 +354,11 @@ WebInspector.TimelinePanel.prototype = { |
| panelStatusBarElement.appendChild(flameChartToggleButton.element); |
| } |
| - this._captureStacksSetting = WebInspector.settings.createSetting("timelineCaptureStacks", true); |
| - this._captureStacksSetting.addChangeListener(this._refreshViews, this); |
| - panelStatusBarElement.appendChild(this._createSettingCheckbox(WebInspector.UIString("Stacks"), |
| - this._captureStacksSetting, |
| - WebInspector.UIString("Capture JavaScript stack on every timeline event"))); |
| + this._captureCausesSetting = WebInspector.settings.createSetting("timelineCaptureCauses", true); |
| + this._captureCausesSetting.addChangeListener(this._refreshViews, this); |
| + panelStatusBarElement.appendChild(this._createSettingCheckbox(WebInspector.UIString("Causes"), |
| + this._captureCausesSetting, |
| + WebInspector.UIString("Capture causes for timeline events (e.g., stack traces)"))); |
| this._captureMemorySetting = WebInspector.settings.createSetting("timelineCaptureMemory", false); |
| panelStatusBarElement.appendChild(this._createSettingCheckbox(WebInspector.UIString("Memory"), |
| this._captureMemorySetting, |
| @@ -639,7 +646,7 @@ WebInspector.TimelinePanel.prototype = { |
| _startRecording: function(userInitiated) |
| { |
| this._userInitiatedRecording = userInitiated; |
| - this._model.startRecording(this._captureStacksSetting.get(), this._captureMemorySetting.get(), this._captureLayersAndPicturesSetting && this._captureLayersAndPicturesSetting.get()); |
| + this._model.startRecording(this._captureCausesSetting.get(), this._captureMemorySetting.get(), this._captureLayersAndPicturesSetting && this._captureLayersAndPicturesSetting.get()); |
| if (this._lazyFrameModel) |
| this._lazyFrameModel.setMergeRecords(false); |
| @@ -996,16 +1003,23 @@ WebInspector.TimelinePanel.prototype = { |
| { |
| var title = WebInspector.TracingTimelineUIUtils.eventStyle(event).title; |
| this.showInDetails(title, content); |
| - if (!event.picture) |
| - return; |
| - var paintProfilerView = this._paintProfilerView(); |
| - this._detailsView.appendTab("paintProfiler", WebInspector.UIString("Paint Profiler"), paintProfilerView); |
| - event.picture.requestObject(onGotObject); |
| - function onGotObject(result) |
| - { |
| - if (!result || !result["skp64"]) |
| - return; |
| - paintProfilerView.setPicture(event.thread.target(), result["skp64"]); |
| + if (event.picture) { |
| + var paintProfilerView = this._paintProfilerView(); |
| + this._detailsView.appendTab("paintProfiler", WebInspector.UIString("Paint Profiler"), paintProfilerView); |
| + event.picture.requestObject(onGotObject); |
| + function onGotObject(result) |
| + { |
| + if (!result || !result["skp64"]) |
| + return; |
| + paintProfilerView.setPicture(event.thread.target(), result["skp64"]); |
| + } |
| + } |
| + if (this._hasCauses(event)) { |
| + var causesView = this._causesView(); |
| + causesView.setContentGenerator(function(event, callback) { |
|
caseq
2014/10/06 12:47:48
This looks like a bit too much inversion of contro
pdr.
2014/10/07 04:36:13
Done.
In the future generateCausesContent may be
|
| + WebInspector.TracingTimelineUIUtils.generateCausesContent(event, this._detailsLinkifier, callback); |
| + }.bind(this, event)); |
| + this._detailsView.appendTab("causes", WebInspector.UIString("Causes"), causesView); |
| } |
| }, |
| @@ -1113,6 +1127,23 @@ WebInspector.TimelinePanel.prototype = { |
| this._detailsView.setContent(title, node); |
| }, |
| + /** |
| + * @param {!WebInspector.TracingModel.Event} event |
| + * @return {boolean} |
| + */ |
| + _hasCauses: function(event) |
| + { |
| + if (!event) |
| + return false; |
| + |
| + // Do not show cause data unless the setting is enabled. This gives us a |
| + // single checkbox and a consistent UI, at the cost of not showing |
| + // initiator data that might be available when the setting is disabled. |
| + var initiator = event.initiator; |
| + return this._captureCausesSetting && this._captureCausesSetting.get() |
|
caseq
2014/10/06 12:47:48
does this._captureCausesSetting ever evaluate to f
pdr.
2014/10/07 04:36:13
I was being too cautious. I don't think we can get
|
| + && ((initiator && initiator.stackTrace) || event.stackTrace); |
| + }, |
| + |
| __proto__: WebInspector.Panel.prototype |
| } |
| @@ -1172,6 +1203,8 @@ WebInspector.TimelineDetailsView.prototype = { |
| appendTab: function(id, tabTitle, view, tabTooltip, userGesture, isCloseable) |
| { |
| WebInspector.TabbedPane.prototype.appendTab.call(this, id, tabTitle, view, tabTooltip); |
| + // FIXME: We should check (this._lastUserSelectedTabId) here so new tabs |
|
caseq
2014/10/06 12:47:48
I think this logic is still producing the effect o
pdr.
2014/10/07 04:36:13
I've pulled this out into https://codereview.chrom
|
| + // are not automatically selected. |
| if (this._lastUserSelectedTabId !== this.selectedTabId) |
| this.selectTab(id); |
| }, |
| @@ -1463,3 +1496,61 @@ WebInspector.TimelinePanelFactory.prototype = { |
| return WebInspector.TimelinePanel._instance(); |
| } |
| } |
| + |
| +/** |
| + * Display information about an event's direct and indirect causes. |
| + * |
| + * @interface |
| + * @extends {WebInspector.VBox} |
| + */ |
| +WebInspector.TimelineCausesView = function() |
| +{ |
| + WebInspector.VBox.call(this); |
| + this.element.classList.add("timeline-causes-view"); |
| +} |
| + |
| +WebInspector.TimelineCausesView.prototype = { |
| + setContentGenerator: function(generator) |
| + { |
| + this._generateContent = generator; |
| + if (this.isShowing()) |
| + this._update(); |
| + else |
| + this._updateWhenVisible = true; |
| + }, |
| + |
| + wasShown: function() |
| + { |
| + WebInspector.View.prototype.wasShown.call(this); |
| + if (this._updateWhenVisible) { |
| + this._updateWhenVisible = false; |
| + this._update(); |
| + } |
| + }, |
| + |
| + _update: function() |
| + { |
| + this.element.removeChildren(); |
| + |
| + if (this._generateContent) { |
| + this._generateContent(function(content) { |
| + var hasContent = content && content.children.length; |
| + var content = hasContent ? content : this._noCauseFoundContent(); |
| + this.element.appendChild(content); |
| + }.bind(this)); |
| + } else { |
| + console.error("No content generator set on TimelineCausesView."); |
| + this.element.appendChild(this._noCauseFoundContent()); |
| + } |
| + }, |
| + |
| + _noCauseFoundContent: function() |
|
caseq
2014/10/06 12:47:48
nit: since it's going to be always the same, just
pdr.
2014/10/07 04:36:13
I wanted to keep this as light as possible, as it
|
| + { |
| + var content = this.element.createChild("div", ""); |
| + content.textContent = |
| + WebInspector.UIString("No causes reported for this event."); |
| + return content; |
| + }, |
| + |
| + __proto__: WebInspector.VBox.prototype |
| +}; |