Index: Source/devtools/front_end/timeline/TracingTimelineModel.js |
diff --git a/Source/devtools/front_end/timeline/TracingTimelineModel.js b/Source/devtools/front_end/timeline/TracingTimelineModel.js |
index 539de3c35f36fbf3004de55c96642d8777785616..c1a52072e7157330c8e6cd5bba5e4696af26264b 100644 |
--- a/Source/devtools/front_end/timeline/TracingTimelineModel.js |
+++ b/Source/devtools/front_end/timeline/TracingTimelineModel.js |
@@ -5,14 +5,16 @@ |
/** |
* @param {!WebInspector.TracingModel} tracingModel |
* @constructor |
- * @extends {WebInspector.TargetAwareObject} |
+ * @extends {WebInspector.TimelineModel} |
*/ |
WebInspector.TracingTimelineModel = function(tracingModel) |
{ |
- WebInspector.TargetAwareObject.call(this, tracingModel.target()); |
+ WebInspector.TimelineModel.call(this, tracingModel.target()); |
this._tracingModel = tracingModel; |
this._mainThreadEvents = []; |
this._inspectedTargetEvents = []; |
+ |
+ this.reset(); |
} |
WebInspector.TracingTimelineModel.RecordType = { |
@@ -112,22 +114,40 @@ WebInspector.TracingTimelineModel.prototype = { |
categoriesArray.push("disabled-by-default-devtools.timeline.stack"); |
categories = categoriesArray.join(","); |
} |
- this._tracingModel.start(categories, ""); |
- this.willStartRecordingTraceEvents(); |
+ this._startRecordingWithCategories(categories); |
}, |
stopRecording: function() |
{ |
- this._tracingModel.stop(this.didStopRecordingTraceEvents.bind(this)); |
+ this._tracingModel.stop(this._didStopRecordingTraceEvents.bind(this)); |
}, |
- willStartRecordingTraceEvents: function() |
+ /** |
+ * @param {string} sessionId |
+ * @param {!Array.<!WebInspector.TracingModel.EventPayload>} events |
+ */ |
+ setEventsForTest: function(sessionId, events) |
{ |
- this._mainThreadEvents = []; |
- this._inspectedTargetEvents = []; |
+ this._didStartRecordingTraceEvents(); |
+ this._tracingModel.setEventsForTest(sessionId, events); |
+ this._didStopRecordingTraceEvents(); |
+ }, |
+ |
+ /** |
+ * @param {string} categories |
+ */ |
+ _startRecordingWithCategories: function(categories) |
+ { |
+ this._tracingModel.start(categories, "", this._didStartRecordingTraceEvents.bind(this)); |
}, |
- didStopRecordingTraceEvents: function() |
+ _didStartRecordingTraceEvents: function() |
+ { |
+ this.reset(); |
+ this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordingStarted); |
+ }, |
+ |
+ _didStopRecordingTraceEvents: function() |
{ |
var events = this._tracingModel.devtoolsMetadataEvents(); |
events.sort(WebInspector.TracingModel.Event.compareStartTime); |
@@ -148,7 +168,9 @@ WebInspector.TracingTimelineModel.prototype = { |
this._inspectedTargetEvents.sort(WebInspector.TracingModel.Event.compareStartTime); |
+ this._buildTimelineRecords(); |
this.dispatchEventToListeners(WebInspector.TracingTimelineModel.Events.TracingComplete); |
+ this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordingStopped); |
caseq
2014/06/09 11:59:03
do we really need two events for this?
yurys
2014/06/09 12:16:13
No. I will address this in a separate patch.
|
}, |
/** |
@@ -183,6 +205,50 @@ WebInspector.TracingTimelineModel.prototype = { |
return this._mainThreadEvents; |
}, |
+ reset: function() |
+ { |
+ this._mainThreadEvents = []; |
+ this._inspectedTargetEvents = []; |
+ WebInspector.TimelineModel.prototype.reset.call(this); |
+ }, |
+ |
+ _buildTimelineRecords: function() |
+ { |
+ var recordStack = []; |
+ var mainThreadEvents = this._mainThreadEvents; |
+ for (var i = 0, size = mainThreadEvents.length; i < size; ++i) { |
+ var event = mainThreadEvents[i]; |
+ while (recordStack.length) { |
+ var top = recordStack.peekLast(); |
+ if (top._event.endTime >= event.startTime) |
+ break; |
+ recordStack.pop(); |
+ } |
+ var parentRecord = recordStack.peekLast() || null; |
+ var record = new WebInspector.TracingTimelineModel.TraceEventRecord(this, event, parentRecord); |
+ if (WebInspector.TimelineUIUtils.isEventDivider(record)) |
+ this._eventDividerRecords.push(record); |
+ if (!recordStack.length) |
+ this._addTopLevelRecord(record); |
+ if (event.endTime) |
+ recordStack.push(record); |
+ } |
+ }, |
+ |
+ /** |
+ * @param {!WebInspector.TracingTimelineModel.TraceEventRecord} record |
+ */ |
+ _addTopLevelRecord: function(record) |
+ { |
+ this._updateBoundaries(record); |
+ this._records.push(record); |
+ if (record.type() === WebInspector.TimelineModel.RecordType.Program) |
+ this._mainThreadTasks.push(record); |
+ if (record.type() === WebInspector.TimelineModel.RecordType.GPUTask) |
+ this._gpuThreadTasks.push(record); |
+ this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAdded, record); |
+ }, |
+ |
_resetProcessingState: function() |
{ |
this._sendRequestEvents = {}; |
@@ -377,5 +443,214 @@ WebInspector.TracingTimelineModel.prototype = { |
return null; |
}, |
- __proto__: WebInspector.TargetAwareObject.prototype |
+ __proto__: WebInspector.TimelineModel.prototype |
+} |
+ |
+/** |
+ * @constructor |
+ * @implements {WebInspector.TimelineModel.Record} |
+ * @param {!WebInspector.TimelineModel} model |
+ * @param {!WebInspector.TracingModel.Event} traceEvent |
+ * @param {?WebInspector.TracingTimelineModel.TraceEventRecord} parentRecord |
+ */ |
+WebInspector.TracingTimelineModel.TraceEventRecord = function(model, traceEvent, parentRecord) |
+{ |
+ this._model = model; |
+ this._event = traceEvent; |
+ traceEvent._timelineRecord = this; |
+ if (parentRecord) { |
+ this.parent = parentRecord; |
+ parentRecord._children.push(this); |
+ } |
+ this._children = []; |
+} |
+ |
+WebInspector.TracingTimelineModel.TraceEventRecord.prototype = { |
+ /** |
+ * @return {?Array.<!ConsoleAgent.CallFrame>} |
+ */ |
+ callSiteStackTrace: function() |
+ { |
+ var initiator = this._event.initiator; |
+ return initiator ? initiator.stackTrace : null; |
+ }, |
+ |
+ /** |
+ * @return {?WebInspector.TimelineModel.Record} |
+ */ |
+ initiator: function() |
+ { |
+ var initiator = this._event.initiator; |
+ return initiator ? initiator._timelineRecord : null; |
+ }, |
+ |
+ /** |
+ * @return {!WebInspector.Target} |
+ */ |
+ target: function() |
+ { |
+ return this._model.target(); |
+ }, |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ selfTime: function() |
+ { |
+ return this._event.selfTime; |
+ }, |
+ |
+ /** |
+ * @return {!Array.<!WebInspector.TimelineModel.Record>} |
+ */ |
+ children: function() |
+ { |
+ return this._children; |
+ }, |
+ |
+ /** |
+ * @return {!WebInspector.TimelineCategory} |
+ */ |
+ category: function() |
+ { |
+ var style = WebInspector.TimelineUIUtils.styleForTimelineEvent(this._event.name); |
+ return style.category; |
+ }, |
+ |
+ /** |
+ * @return {string} |
+ */ |
+ title: function() |
+ { |
+ return WebInspector.TimelineUIUtils.recordTitle(this, this._model); |
+ }, |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ startTime: function() |
+ { |
+ return this._event.startTime; |
+ }, |
+ |
+ /** |
+ * @return {string|undefined} |
+ */ |
+ thread: function() |
+ { |
+ return "CPU"; |
+ }, |
+ |
+ /** |
+ * @return {number} |
+ */ |
+ endTime: function() |
+ { |
+ return this._event.endTime || this._event.startTime; |
+ }, |
+ |
+ /** |
+ * @param {number} endTime |
+ */ |
+ setEndTime: function(endTime) |
+ { |
+ throw new Error("Unsupported operation setEndTime"); |
+ }, |
+ |
+ /** |
+ * @return {!Object} |
+ */ |
+ data: function() |
+ { |
+ return this._event.args.data; |
+ }, |
+ |
+ /** |
+ * @return {string} |
+ */ |
+ type: function() |
+ { |
+ return this._event.name; |
+ }, |
+ |
+ /** |
+ * @return {string} |
+ */ |
+ frameId: function() |
+ { |
+ switch (this._event.name) { |
+ case WebInspector.TracingTimelineModel.RecordType.ScheduleStyleRecalculation: |
+ case WebInspector.TracingTimelineModel.RecordType.RecalculateStyles: |
+ case WebInspector.TracingTimelineModel.RecordType.InvalidateLayout: |
+ return this._event.args["frameId"]; |
+ case WebInspector.TracingTimelineModel.RecordType.Layout: |
+ return this._event.args["beginData"]["frameId"]; |
+ default: |
+ var data = this._event.args.data; |
+ return (data && data["frame"]) || ""; |
+ } |
+ }, |
+ |
+ /** |
+ * @return {?Array.<!ConsoleAgent.CallFrame>} |
+ */ |
+ stackTrace: function() |
+ { |
+ return this._event.stackTrace; |
+ }, |
+ |
+ /** |
+ * @param {string} key |
+ * @return {?Object} |
+ */ |
+ getUserObject: function(key) |
+ { |
+ if (key === "TimelineUIUtils::preview-element") |
+ return this._event.previewElement; |
+ throw new Error("Unexpected key: " + key); |
+ }, |
+ |
+ /** |
+ * @param {string} key |
+ * @param {?Object|undefined} value |
+ */ |
+ setUserObject: function(key, value) |
+ { |
+ if (key !== "TimelineUIUtils::preview-element") |
+ throw new Error("Unexpected key: " + key); |
+ this._event.previewElement = /** @type {?Element} */ (value); |
+ }, |
+ |
+ /** |
+ * @return {!Object.<string, number>} |
+ */ |
+ aggregatedStats: function() |
+ { |
+ return {}; |
+ }, |
+ |
+ /** |
+ * @return {?Array.<string>} |
+ */ |
+ warnings: function() |
+ { |
+ if (this._event.warning) |
+ return [this._event.warning]; |
+ return null; |
+ }, |
+ |
+ /** |
+ * @param {!RegExp} regExp |
+ * @return {boolean} |
+ */ |
+ testContentMatching: function(regExp) |
+ { |
+ var tokens = [this.title()]; |
+ var data = this._event.args.data; |
+ if (data) { |
+ for (var key in data) |
+ tokens.push(data[key]); |
+ } |
+ return regExp.test(tokens.join("|")); |
+ } |
} |