Index: Source/devtools/front_end/timeline/TimelineModel.js |
diff --git a/Source/devtools/front_end/timeline/TimelineModel.js b/Source/devtools/front_end/timeline/TimelineModel.js |
index f56571beaca93a2f7be3daf91deda39217b872c2..ad7f11e4278dc8f45e0495b2359e26e7994fb208 100644 |
--- a/Source/devtools/front_end/timeline/TimelineModel.js |
+++ b/Source/devtools/front_end/timeline/TimelineModel.js |
@@ -164,8 +164,8 @@ WebInspector.TimelineModel.Events = { |
} |
WebInspector.TimelineModel.MainThreadName = "main"; |
- |
WebInspector.TimelineModel.WorkerThreadName = "DedicatedWorker Thread"; |
+WebInspector.TimelineModel.RendererMainThreadName = "CrRendererMain"; |
/** |
* @param {!Array.<!WebInspector.TracingModel.Event>} events |
@@ -224,6 +224,11 @@ WebInspector.TimelineModel.forAllRecords = function(recordsArray, preOrderCallba |
WebInspector.TimelineModel.TransferChunkLengthBytes = 5000000; |
+WebInspector.TimelineModel.DevToolsMetadataEvent = { |
+ TracingStartedInPage: "TracingStartedInPage", |
+ TracingSessionIdForWorker: "TracingSessionIdForWorker", |
+}; |
+ |
/** |
* @constructor |
* @param {string} name |
@@ -295,7 +300,9 @@ WebInspector.TimelineModel.Record.prototype = { |
*/ |
target: function() |
{ |
- return this._event.thread.target(); |
+ var threadName = this._event.thread.name(); |
+ //FIXME: correctly specify target |
+ return threadName === WebInspector.TimelineModel.RendererMainThreadName ? WebInspector.targetManager.targets()[0] || null : null; |
}, |
/** |
@@ -327,7 +334,7 @@ WebInspector.TimelineModel.Record.prototype = { |
*/ |
thread: function() |
{ |
- if (this._event.thread.name() === "CrRendererMain") |
+ if (this._event.thread.name() === WebInspector.TimelineModel.RendererMainThreadName) |
return WebInspector.TimelineModel.MainThreadName; |
return this._event.thread.name(); |
}, |
@@ -448,6 +455,9 @@ WebInspector.TimelineModel.Record.prototype = { |
} |
} |
+/** @typedef {!{page: !Array<!WebInspector.TracingModel.Event>, workers: !Array<!WebInspector.TracingModel.Event>}} */ |
+WebInspector.TimelineModel.MetadataEvents; |
+ |
WebInspector.TimelineModel.prototype = { |
/** |
* @param {boolean} captureCauses |
@@ -578,6 +588,14 @@ WebInspector.TimelineModel.prototype = { |
}, |
/** |
+ * @return {?string} |
+ */ |
+ sessionId: function() |
+ { |
+ return this._sessionId; |
+ }, |
+ |
+ /** |
* @return {?WebInspector.Target} |
*/ |
target: function() |
@@ -757,21 +775,19 @@ WebInspector.TimelineModel.prototype = { |
_didStopRecordingTraceEvents: function() |
{ |
- this._injectCpuProfileEvents(); |
+ var metadataEvents = this._processMetadataEvents(); |
+ this._injectCpuProfileEvents(metadataEvents); |
this._tracingModel.tracingComplete(); |
- var metaEvents = this._tracingModel.devtoolsPageMetadataEvents(); |
- var workerMetadataEvents = this._tracingModel.devtoolsWorkerMetadataEvents(); |
- |
this._resetProcessingState(); |
var startTime = 0; |
- for (var i = 0, length = metaEvents.length; i < length; i++) { |
- var metaEvent = metaEvents[i]; |
+ for (var i = 0, length = metadataEvents.page.length; i < length; i++) { |
+ var metaEvent = metadataEvents.page[i]; |
var process = metaEvent.thread.process(); |
- var endTime = i + 1 < length ? metaEvents[i + 1].startTime : Infinity; |
+ var endTime = i + 1 < length ? metadataEvents.page[i + 1].startTime : Infinity; |
this._currentPage = metaEvent.args["data"] && metaEvent.args["data"]["page"]; |
for (var thread of process.sortedThreads()) { |
- if (thread.name() === WebInspector.TimelineModel.WorkerThreadName && !workerMetadataEvents.some(function(e) { return e.args["data"]["workerThreadId"] === thread.id(); })) |
+ if (thread.name() === WebInspector.TimelineModel.WorkerThreadName && !metadataEvents.workers.some(function(e) { return e.args["data"]["workerThreadId"] === thread.id(); })) |
continue; |
this._processThreadEvents(startTime, endTime, metaEvent.thread, thread); |
} |
@@ -789,6 +805,79 @@ WebInspector.TimelineModel.prototype = { |
}, |
/** |
+ * @return {!WebInspector.TimelineModel.MetadataEvents} |
+ */ |
+ _processMetadataEvents: function() |
+ { |
+ var metadataEvents = this._tracingModel.devToolsMetadataEvents(); |
+ |
+ var pageDevToolsMetadataEvents = []; |
+ var workersDevToolsMetadataEvents = []; |
+ for (var event of metadataEvents) { |
+ if (event.name === WebInspector.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage) |
+ pageDevToolsMetadataEvents.push(event); |
+ else if (event.name === WebInspector.TimelineModel.DevToolsMetadataEvent.TracingSessionIdForWorker) |
+ workersDevToolsMetadataEvents.push(event); |
+ } |
+ if (!pageDevToolsMetadataEvents.length) { |
+ // The trace is probably coming not from DevTools. Make a mock Metadata event. |
+ var pageMetaEvent = this._loadedFromFile ? this._makeMockPageMetadataEvent() : null; |
+ if (!pageMetaEvent) { |
+ console.error(WebInspector.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage + " event not found."); |
+ return {page: [], workers: []}; |
+ } |
+ pageDevToolsMetadataEvents.push(pageMetaEvent); |
+ } |
+ var sessionId = pageDevToolsMetadataEvents[0].args["sessionId"] || pageDevToolsMetadataEvents[0].args["data"]["sessionId"]; |
+ this._sessionId = sessionId; |
+ |
+ var mismatchingIds = new Set(); |
+ /** |
+ * @param {!WebInspector.TracingModel.Event} event |
+ * @return {boolean} |
+ */ |
+ function checkSessionId(event) |
+ { |
+ var args = event.args; |
+ // FIXME: put sessionId into args["data"] for TracingStartedInPage event. |
+ if (args["data"]) |
+ args = args["data"]; |
+ var id = args["sessionId"]; |
+ if (id === sessionId) |
+ return true; |
+ mismatchingIds.add(id); |
+ return false; |
+ } |
+ var result = { |
+ page: pageDevToolsMetadataEvents.filter(checkSessionId).sort(WebInspector.TracingModel.Event.compareStartTime), |
+ workers: workersDevToolsMetadataEvents.filter(checkSessionId).sort(WebInspector.TracingModel.Event.compareStartTime) |
+ }; |
+ if (mismatchingIds.size) |
+ WebInspector.console.error("Timeline recording was started in more than one page simultaneously. Session id mismatch: " + this._sessionId + " and " + mismatchingIds.valuesArray() + "."); |
+ return result; |
+ }, |
+ |
+ /** |
+ * @return {?WebInspector.TracingModel.Event} |
+ */ |
+ _makeMockPageMetadataEvent: function() |
+ { |
+ var rendererMainThreadName = WebInspector.TimelineModel.RendererMainThreadName; |
+ // FIXME: pick up the first renderer process for now. |
+ var process = Object.values(this._tracingModel.sortedProcesses()).filter(function(p) { return p.threadByName(rendererMainThreadName); })[0]; |
+ var thread = process && process.threadByName(rendererMainThreadName); |
+ if (!thread) |
+ return null; |
+ var pageMetaEvent = new WebInspector.TracingModel.Event( |
+ WebInspector.TracingModel.DevToolsMetadataEventCategory, |
+ WebInspector.TimelineModel.DevToolsMetadataEvent.TracingStartedInPage, |
+ WebInspector.TracingModel.Phase.Metadata, |
+ this._tracingModel.minimumRecordTime(), thread); |
+ pageMetaEvent.addArgs({"data": {"sessionId": "mockSessionId"}}); |
+ return pageMetaEvent; |
+ }, |
+ |
+ /** |
* @param {number} pid |
* @param {number} tid |
* @param {?ProfilerAgent.CPUProfile} cpuProfile |
@@ -809,19 +898,21 @@ WebInspector.TimelineModel.prototype = { |
this._tracingModel.addEvents([cpuProfileEvent]); |
}, |
- _injectCpuProfileEvents: function() |
+ /** |
+ * @param {!WebInspector.TimelineModel.MetadataEvents} metadataEvents |
+ */ |
+ _injectCpuProfileEvents: function(metadataEvents) |
{ |
if (!this._cpuProfiles) |
return; |
- var mainMetaEvent = this._tracingModel.devtoolsPageMetadataEvents().peekLast(); |
+ var mainMetaEvent = metadataEvents.page.peekLast(); |
if (!mainMetaEvent) |
return; |
var pid = mainMetaEvent.thread.process().id(); |
var mainTarget = this._targets[0]; |
var mainCpuProfile = this._cpuProfiles.get(mainTarget.id()); |
this._injectCpuProfileEvent(pid, mainMetaEvent.thread.id(), mainCpuProfile); |
- var workerMetadataEvents = this._tracingModel.devtoolsWorkerMetadataEvents(); |
- for (var metaEvent of workerMetadataEvents) { |
+ for (var metaEvent of metadataEvents.workers) { |
var workerId = metaEvent.args["data"]["workerId"]; |
var target = mainTarget.workerManager ? mainTarget.workerManager.targetByWorkerId(workerId) : null; |
if (!target) |
@@ -1298,6 +1389,9 @@ WebInspector.TimelineModel.prototype = { |
this._gpuTasks = []; |
/** @type {!Array.<!WebInspector.TimelineModel.Record>} */ |
this._eventDividerRecords = []; |
+ /** @type {?string} */ |
+ this._sessionId = null; |
+ this._loadedFromFile = false; |
this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordsCleared); |
}, |
@@ -1886,7 +1980,6 @@ WebInspector.ExcludeTopLevelFilter.prototype = { |
WebInspector.TracingModelLoader = function(model, progress, canceledCallback) |
{ |
this._model = model; |
- this._loader = new WebInspector.TracingModel.Loader(model._tracingModel); |
this._canceledCallback = canceledCallback; |
this._progress = progress; |
@@ -1983,7 +2076,7 @@ WebInspector.TracingModelLoader.prototype = { |
} |
try { |
- this._loader.loadNextChunk(items); |
+ this._model._tracingModel.addEvents(items); |
} catch(e) { |
this._reportErrorAndCancelLoading(WebInspector.UIString("Malformed timeline data: %s", e.toString())); |
return; |
@@ -2014,7 +2107,7 @@ WebInspector.TracingModelLoader.prototype = { |
*/ |
close: function() |
{ |
- this._loader.finish(); |
+ this._model._loadedFromFile = true; |
this._model.tracingComplete(); |
if (this._progress) |
this._progress.done(); |