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 |
+}; |