Chromium Code Reviews| 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("|")); |
| + } |
| } |