| OLD | NEW |
| 1 /* | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 * | 3 // found in the LICENSE file. |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 */ | |
| 30 | 4 |
| 31 /** | 5 /** |
| 32 * @constructor | 6 * @constructor |
| 33 * @extends {WebInspector.Object} | 7 * @extends {WebInspector.TimelineModel} |
| 34 * @param {!WebInspector.TimelineManager} timelineManager | 8 * @param {!WebInspector.TimelineManager} timelineManager |
| 35 */ | 9 */ |
| 36 WebInspector.TimelineModel = function(timelineManager) | 10 WebInspector.TimelineModelImpl = function(timelineManager) |
| 37 { | 11 { |
| 12 WebInspector.TimelineModel.call(this, timelineManager.target()); |
| 38 this._timelineManager = timelineManager; | 13 this._timelineManager = timelineManager; |
| 39 this._filters = []; | 14 this._filters = []; |
| 40 this._bindings = new WebInspector.TimelineModel.InterRecordBindings(); | 15 this._bindings = new WebInspector.TimelineModelImpl.InterRecordBindings(); |
| 41 | 16 |
| 42 this.reset(); | 17 this.reset(); |
| 43 | 18 |
| 44 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp
es.TimelineEventRecorded, this._onRecordAdded, this); | 19 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp
es.TimelineEventRecorded, this._onRecordAdded, this); |
| 45 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp
es.TimelineStarted, this._onStarted, this); | 20 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp
es.TimelineStarted, this._onStarted, this); |
| 46 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp
es.TimelineStopped, this._onStopped, this); | 21 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp
es.TimelineStopped, this._onStopped, this); |
| 47 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp
es.TimelineProgress, this._onProgress, this); | 22 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp
es.TimelineProgress, this._onProgress, this); |
| 48 } | 23 } |
| 49 | 24 |
| 50 WebInspector.TimelineModel.TransferChunkLengthBytes = 5000000; | 25 WebInspector.TimelineModelImpl.TransferChunkLengthBytes = 5000000; |
| 51 | 26 |
| 52 WebInspector.TimelineModel.RecordType = { | 27 WebInspector.TimelineModelImpl.prototype = { |
| 53 Root: "Root", | |
| 54 Program: "Program", | |
| 55 EventDispatch: "EventDispatch", | |
| 56 | |
| 57 GPUTask: "GPUTask", | |
| 58 | |
| 59 RequestMainThreadFrame: "RequestMainThreadFrame", | |
| 60 BeginFrame: "BeginFrame", | |
| 61 ActivateLayerTree: "ActivateLayerTree", | |
| 62 DrawFrame: "DrawFrame", | |
| 63 ScheduleStyleRecalculation: "ScheduleStyleRecalculation", | |
| 64 RecalculateStyles: "RecalculateStyles", | |
| 65 InvalidateLayout: "InvalidateLayout", | |
| 66 Layout: "Layout", | |
| 67 UpdateLayerTree: "UpdateLayerTree", | |
| 68 PaintSetup: "PaintSetup", | |
| 69 Paint: "Paint", | |
| 70 Rasterize: "Rasterize", | |
| 71 ScrollLayer: "ScrollLayer", | |
| 72 DecodeImage: "DecodeImage", | |
| 73 ResizeImage: "ResizeImage", | |
| 74 CompositeLayers: "CompositeLayers", | |
| 75 | |
| 76 ParseHTML: "ParseHTML", | |
| 77 | |
| 78 TimerInstall: "TimerInstall", | |
| 79 TimerRemove: "TimerRemove", | |
| 80 TimerFire: "TimerFire", | |
| 81 | |
| 82 XHRReadyStateChange: "XHRReadyStateChange", | |
| 83 XHRLoad: "XHRLoad", | |
| 84 EvaluateScript: "EvaluateScript", | |
| 85 | |
| 86 MarkLoad: "MarkLoad", | |
| 87 MarkDOMContent: "MarkDOMContent", | |
| 88 MarkFirstPaint: "MarkFirstPaint", | |
| 89 | |
| 90 TimeStamp: "TimeStamp", | |
| 91 ConsoleTime: "ConsoleTime", | |
| 92 | |
| 93 ResourceSendRequest: "ResourceSendRequest", | |
| 94 ResourceReceiveResponse: "ResourceReceiveResponse", | |
| 95 ResourceReceivedData: "ResourceReceivedData", | |
| 96 ResourceFinish: "ResourceFinish", | |
| 97 | |
| 98 FunctionCall: "FunctionCall", | |
| 99 GCEvent: "GCEvent", | |
| 100 JSFrame: "JSFrame", | |
| 101 | |
| 102 UpdateCounters: "UpdateCounters", | |
| 103 | |
| 104 RequestAnimationFrame: "RequestAnimationFrame", | |
| 105 CancelAnimationFrame: "CancelAnimationFrame", | |
| 106 FireAnimationFrame: "FireAnimationFrame", | |
| 107 | |
| 108 WebSocketCreate : "WebSocketCreate", | |
| 109 WebSocketSendHandshakeRequest : "WebSocketSendHandshakeRequest", | |
| 110 WebSocketReceiveHandshakeResponse : "WebSocketReceiveHandshakeResponse", | |
| 111 WebSocketDestroy : "WebSocketDestroy", | |
| 112 | |
| 113 EmbedderCallback : "EmbedderCallback", | |
| 114 } | |
| 115 | |
| 116 WebInspector.TimelineModel.Events = { | |
| 117 RecordAdded: "RecordAdded", | |
| 118 RecordsCleared: "RecordsCleared", | |
| 119 RecordingStarted: "RecordingStarted", | |
| 120 RecordingStopped: "RecordingStopped", | |
| 121 RecordingProgress: "RecordingProgress", | |
| 122 RecordFilterChanged: "RecordFilterChanged" | |
| 123 } | |
| 124 | |
| 125 /** | |
| 126 * @param {!Array.<!WebInspector.TimelineModel.Record>} recordsArray | |
| 127 * @param {?function(!WebInspector.TimelineModel.Record)|?function(!WebInspector
.TimelineModel.Record,number)} preOrderCallback | |
| 128 * @param {function(!WebInspector.TimelineModel.Record)|function(!WebInspector.T
imelineModel.Record,number)=} postOrderCallback | |
| 129 * @return {boolean} | |
| 130 */ | |
| 131 WebInspector.TimelineModel.forAllRecords = function(recordsArray, preOrderCallba
ck, postOrderCallback) | |
| 132 { | |
| 133 /** | |
| 134 * @param {!Array.<!WebInspector.TimelineModel.Record>} records | |
| 135 * @param {number} depth | |
| 136 * @return {boolean} | |
| 137 */ | |
| 138 function processRecords(records, depth) | |
| 139 { | |
| 140 for (var i = 0; i < records.length; ++i) { | |
| 141 var record = records[i]; | |
| 142 if (preOrderCallback && preOrderCallback(record, depth)) | |
| 143 return true; | |
| 144 if (processRecords(record.children(), depth + 1)) | |
| 145 return true; | |
| 146 if (postOrderCallback && postOrderCallback(record, depth)) | |
| 147 return true; | |
| 148 } | |
| 149 return false; | |
| 150 } | |
| 151 return processRecords(recordsArray, 0); | |
| 152 } | |
| 153 | |
| 154 WebInspector.TimelineModel.prototype = { | |
| 155 /** | |
| 156 * @return {!WebInspector.Target} | |
| 157 */ | |
| 158 target: function() | |
| 159 { | |
| 160 return this._timelineManager.target(); | |
| 161 }, | |
| 162 | |
| 163 /** | 28 /** |
| 164 * @return {boolean} | 29 * @return {boolean} |
| 165 */ | 30 */ |
| 166 loadedFromFile: function() | 31 loadedFromFile: function() |
| 167 { | 32 { |
| 168 return this._loadedFromFile; | 33 return this._loadedFromFile; |
| 169 }, | 34 }, |
| 170 | 35 |
| 171 /** | 36 /** |
| 172 * @param {?function(!WebInspector.TimelineModel.Record)|?function(!WebInspe
ctor.TimelineModel.Record,number)} preOrderCallback | |
| 173 * @param {function(!WebInspector.TimelineModel.Record)|function(!WebInspect
or.TimelineModel.Record,number)=} postOrderCallback | |
| 174 */ | |
| 175 forAllRecords: function(preOrderCallback, postOrderCallback) | |
| 176 { | |
| 177 WebInspector.TimelineModel.forAllRecords(this._records, preOrderCallback
, postOrderCallback); | |
| 178 }, | |
| 179 | |
| 180 /** | |
| 181 * @param {!WebInspector.TimelineModel.Filter} filter | |
| 182 */ | |
| 183 addFilter: function(filter) | |
| 184 { | |
| 185 this._filters.push(filter); | |
| 186 filter._model = this; | |
| 187 }, | |
| 188 | |
| 189 /** | |
| 190 * @param {function(!WebInspector.TimelineModel.Record)|function(!WebInspect
or.TimelineModel.Record,number)} callback | |
| 191 */ | |
| 192 forAllFilteredRecords: function(callback) | |
| 193 { | |
| 194 /** | |
| 195 * @param {!WebInspector.TimelineModel.Record} record | |
| 196 * @param {number} depth | |
| 197 * @this {WebInspector.TimelineModel} | |
| 198 * @return {boolean} | |
| 199 */ | |
| 200 function processRecord(record, depth) | |
| 201 { | |
| 202 var visible = this.isVisible(record); | |
| 203 if (visible) { | |
| 204 if (callback(record, depth)) | |
| 205 return true; | |
| 206 } | |
| 207 | |
| 208 for (var i = 0; i < record.children().length; ++i) { | |
| 209 if (processRecord.call(this, record.children()[i], visible ? dep
th + 1 : depth)) | |
| 210 return true; | |
| 211 } | |
| 212 return false; | |
| 213 } | |
| 214 | |
| 215 for (var i = 0; i < this._records.length; ++i) | |
| 216 processRecord.call(this, this._records[i], 0); | |
| 217 }, | |
| 218 | |
| 219 /** | |
| 220 * @param {!WebInspector.TimelineModel.Record} record | |
| 221 * @return {boolean} | |
| 222 */ | |
| 223 isVisible: function(record) | |
| 224 { | |
| 225 for (var i = 0; i < this._filters.length; ++i) { | |
| 226 if (!this._filters[i].accept(record)) | |
| 227 return false; | |
| 228 } | |
| 229 return true; | |
| 230 }, | |
| 231 | |
| 232 _filterChanged: function() | |
| 233 { | |
| 234 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordFi
lterChanged); | |
| 235 }, | |
| 236 | |
| 237 /** | |
| 238 * @param {boolean} captureStacks | 37 * @param {boolean} captureStacks |
| 239 * @param {boolean} captureMemory | 38 * @param {boolean} captureMemory |
| 240 */ | 39 */ |
| 241 startRecording: function(captureStacks, captureMemory) | 40 startRecording: function(captureStacks, captureMemory) |
| 242 { | 41 { |
| 243 this._clientInitiatedRecording = true; | 42 this._clientInitiatedRecording = true; |
| 244 this.reset(); | 43 this.reset(); |
| 245 var maxStackFrames = captureStacks ? 30 : 0; | 44 var maxStackFrames = captureStacks ? 30 : 0; |
| 246 this._bufferEvents = WebInspector.experimentsSettings.timelineNoLiveUpda
te.isEnabled(); | 45 this._bufferEvents = WebInspector.experimentsSettings.timelineNoLiveUpda
te.isEnabled(); |
| 247 var includeGPUEvents = WebInspector.experimentsSettings.gpuTimeline.isEn
abled(); | 46 var includeGPUEvents = WebInspector.experimentsSettings.gpuTimeline.isEn
abled(); |
| 248 var liveEvents = [ WebInspector.TimelineModel.RecordType.BeginFrame, | 47 var liveEvents = [ WebInspector.TimelineModel.RecordType.BeginFrame, |
| 249 WebInspector.TimelineModel.RecordType.DrawFrame, | 48 WebInspector.TimelineModel.RecordType.DrawFrame, |
| 250 WebInspector.TimelineModel.RecordType.RequestMainThre
adFrame, | 49 WebInspector.TimelineModel.RecordType.RequestMainThre
adFrame, |
| 251 WebInspector.TimelineModel.RecordType.ActivateLayerTr
ee ]; | 50 WebInspector.TimelineModel.RecordType.ActivateLayerTr
ee ]; |
| 252 this._timelineManager.start(maxStackFrames, this._bufferEvents, liveEven
ts.join(","), captureMemory, includeGPUEvents, this._fireRecordingStarted.bind(t
his)); | 51 this._timelineManager.start(maxStackFrames, this._bufferEvents, liveEven
ts.join(","), captureMemory, includeGPUEvents, this._fireRecordingStarted.bind(t
his)); |
| 253 }, | 52 }, |
| 254 | 53 |
| 255 stopRecording: function() | 54 stopRecording: function() |
| 256 { | 55 { |
| 257 if (!this._clientInitiatedRecording) { | 56 if (!this._clientInitiatedRecording) { |
| 258 this._timelineManager.start(undefined, undefined, undefined, undefin
ed, undefined, stopTimeline.bind(this)); | 57 this._timelineManager.start(undefined, undefined, undefined, undefin
ed, undefined, stopTimeline.bind(this)); |
| 259 return; | 58 return; |
| 260 } | 59 } |
| 261 | 60 |
| 262 /** | 61 /** |
| 263 * Console started this one and we are just sniffing it. Initiate record
ing so that we | 62 * Console started this one and we are just sniffing it. Initiate record
ing so that we |
| 264 * could stop it. | 63 * could stop it. |
| 265 * @this {WebInspector.TimelineModel} | 64 * @this {WebInspector.TimelineModelImpl} |
| 266 */ | 65 */ |
| 267 function stopTimeline() | 66 function stopTimeline() |
| 268 { | 67 { |
| 269 this._timelineManager.stop(this._fireRecordingStopped.bind(this)); | 68 this._timelineManager.stop(this._fireRecordingStopped.bind(this)); |
| 270 } | 69 } |
| 271 | 70 |
| 272 this._clientInitiatedRecording = false; | 71 this._clientInitiatedRecording = false; |
| 273 this._timelineManager.stop(this._fireRecordingStopped.bind(this)); | 72 this._timelineManager.stop(this._fireRecordingStopped.bind(this)); |
| 274 }, | 73 }, |
| 275 | 74 |
| 276 willStartRecordingTraceEvents: function() | |
| 277 { | |
| 278 this.reset(); | |
| 279 this._fireRecordingStarted(); | |
| 280 }, | |
| 281 | |
| 282 /** | |
| 283 * @param {!Array.<!WebInspector.TracingModel.Event>} mainThreadEvents | |
| 284 */ | |
| 285 didStopRecordingTraceEvents: function(mainThreadEvents) | |
| 286 { | |
| 287 var recordStack = []; | |
| 288 for (var i = 0, size = mainThreadEvents.length; i < size; ++i) { | |
| 289 var event = mainThreadEvents[i]; | |
| 290 while (recordStack.length) { | |
| 291 var top = recordStack.peekLast(); | |
| 292 if (top._event.endTime >= event.startTime) | |
| 293 break; | |
| 294 recordStack.pop(); | |
| 295 } | |
| 296 var parentRecord = recordStack.peekLast() || null; | |
| 297 var record = new WebInspector.TimelineModel.TraceEventRecord(this, e
vent, parentRecord); | |
| 298 if (WebInspector.TimelineUIUtils.isEventDivider(record)) | |
| 299 this._eventDividerRecords.push(record); | |
| 300 if (!recordStack.length) | |
| 301 this._addTopLevelRecord(record); | |
| 302 if (event.endTime) | |
| 303 recordStack.push(record); | |
| 304 } | |
| 305 this._fireRecordingStopped(null, null); | |
| 306 }, | |
| 307 | |
| 308 /** | |
| 309 * @param {!WebInspector.TimelineModel.TraceEventRecord} record | |
| 310 */ | |
| 311 _addTopLevelRecord: function(record) | |
| 312 { | |
| 313 this._updateBoundaries(record); | |
| 314 this._records.push(record); | |
| 315 if (record.type() === WebInspector.TimelineModel.RecordType.Program) | |
| 316 this._mainThreadTasks.push(record); | |
| 317 if (record.type() === WebInspector.TimelineModel.RecordType.GPUTask) | |
| 318 this._gpuThreadTasks.push(record); | |
| 319 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAd
ded, record); | |
| 320 }, | |
| 321 | |
| 322 /** | 75 /** |
| 323 * @return {!Array.<!WebInspector.TimelineModel.Record>} | 76 * @return {!Array.<!WebInspector.TimelineModel.Record>} |
| 324 */ | 77 */ |
| 325 records: function() | 78 records: function() |
| 326 { | 79 { |
| 327 return this._records; | 80 return this._records; |
| 328 }, | 81 }, |
| 329 | 82 |
| 330 /** | 83 /** |
| 331 * @param {!WebInspector.Event} event | 84 * @param {!WebInspector.Event} event |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 loadFromURL: function(url, progress) | 205 loadFromURL: function(url, progress) |
| 453 { | 206 { |
| 454 var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this,
progress); | 207 var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this,
progress); |
| 455 var urlReader = new WebInspector.ChunkedXHRReader(url, delegate); | 208 var urlReader = new WebInspector.ChunkedXHRReader(url, delegate); |
| 456 var loader = new WebInspector.TimelineModelLoader(this, urlReader, progr
ess); | 209 var loader = new WebInspector.TimelineModelLoader(this, urlReader, progr
ess); |
| 457 urlReader.start(loader); | 210 urlReader.start(loader); |
| 458 }, | 211 }, |
| 459 | 212 |
| 460 _createFileReader: function(file, delegate) | 213 _createFileReader: function(file, delegate) |
| 461 { | 214 { |
| 462 return new WebInspector.ChunkedFileReader(file, WebInspector.TimelineMod
el.TransferChunkLengthBytes, delegate); | 215 return new WebInspector.ChunkedFileReader(file, WebInspector.TimelineMod
elImpl.TransferChunkLengthBytes, delegate); |
| 463 }, | 216 }, |
| 464 | 217 |
| 465 _createFileWriter: function() | 218 _createFileWriter: function() |
| 466 { | 219 { |
| 467 return new WebInspector.FileOutputStream(); | 220 return new WebInspector.FileOutputStream(); |
| 468 }, | 221 }, |
| 469 | 222 |
| 470 saveToFile: function() | 223 saveToFile: function() |
| 471 { | 224 { |
| 472 var now = new Date(); | 225 var now = new Date(); |
| 473 var fileName = "TimelineRawData-" + now.toISO8601Compact() + ".json"; | 226 var fileName = "TimelineRawData-" + now.toISO8601Compact() + ".json"; |
| 474 var stream = this._createFileWriter(); | 227 var stream = this._createFileWriter(); |
| 475 | 228 |
| 476 /** | 229 /** |
| 477 * @param {boolean} accepted | 230 * @param {boolean} accepted |
| 478 * @this {WebInspector.TimelineModel} | 231 * @this {WebInspector.TimelineModelImpl} |
| 479 */ | 232 */ |
| 480 function callback(accepted) | 233 function callback(accepted) |
| 481 { | 234 { |
| 482 if (!accepted) | 235 if (!accepted) |
| 483 return; | 236 return; |
| 484 var saver = new WebInspector.TimelineSaver(stream); | 237 var saver = new WebInspector.TimelineSaver(stream); |
| 485 saver.save(this._payloads, window.navigator.appVersion); | 238 saver.save(this._payloads, window.navigator.appVersion); |
| 486 } | 239 } |
| 487 stream.open(fileName, callback.bind(this)); | 240 stream.open(fileName, callback.bind(this)); |
| 488 }, | 241 }, |
| 489 | 242 |
| 490 reset: function() | 243 reset: function() |
| 491 { | 244 { |
| 492 this._loadedFromFile = false; | 245 this._loadedFromFile = false; |
| 493 this._records = []; | |
| 494 this._payloads = []; | 246 this._payloads = []; |
| 495 this._stringPool = {}; | 247 this._stringPool = {}; |
| 496 this._minimumRecordTime = -1; | |
| 497 this._maximumRecordTime = -1; | |
| 498 this._bindings._reset(); | 248 this._bindings._reset(); |
| 499 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */ | 249 WebInspector.TimelineModel.prototype.reset.call(this); |
| 500 this._mainThreadTasks = []; | |
| 501 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */ | |
| 502 this._gpuThreadTasks = []; | |
| 503 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */ | |
| 504 this._eventDividerRecords = []; | |
| 505 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordsC
leared); | |
| 506 }, | 250 }, |
| 507 | 251 |
| 508 /** | 252 /** |
| 509 * @return {number} | |
| 510 */ | |
| 511 minimumRecordTime: function() | |
| 512 { | |
| 513 return this._minimumRecordTime; | |
| 514 }, | |
| 515 | |
| 516 /** | |
| 517 * @return {number} | |
| 518 */ | |
| 519 maximumRecordTime: function() | |
| 520 { | |
| 521 return this._maximumRecordTime; | |
| 522 }, | |
| 523 | |
| 524 /** | |
| 525 * @param {!WebInspector.TimelineModel.Record} record | |
| 526 */ | |
| 527 _updateBoundaries: function(record) | |
| 528 { | |
| 529 var startTime = record.startTime(); | |
| 530 var endTime = record.endTime(); | |
| 531 | |
| 532 if (this._minimumRecordTime === -1 || startTime < this._minimumRecordTim
e) | |
| 533 this._minimumRecordTime = startTime; | |
| 534 if ((this._maximumRecordTime === -1 && endTime) || endTime > this._maxim
umRecordTime) | |
| 535 this._maximumRecordTime = endTime; | |
| 536 }, | |
| 537 | |
| 538 /** | |
| 539 * @return {!Array.<!WebInspector.TimelineModel.Record>} | |
| 540 */ | |
| 541 mainThreadTasks: function() | |
| 542 { | |
| 543 return this._mainThreadTasks; | |
| 544 }, | |
| 545 | |
| 546 /** | |
| 547 * @return {!Array.<!WebInspector.TimelineModel.Record>} | |
| 548 */ | |
| 549 gpuThreadTasks: function() | |
| 550 { | |
| 551 return this._gpuThreadTasks; | |
| 552 }, | |
| 553 | |
| 554 /** | |
| 555 * @return {!Array.<!WebInspector.TimelineModel.Record>} | |
| 556 */ | |
| 557 eventDividerRecords: function() | |
| 558 { | |
| 559 return this._eventDividerRecords; | |
| 560 }, | |
| 561 | |
| 562 /** | |
| 563 * @param {!TimelineAgent.TimelineEvent} record | 253 * @param {!TimelineAgent.TimelineEvent} record |
| 564 */ | 254 */ |
| 565 _internStrings: function(record) | 255 _internStrings: function(record) |
| 566 { | 256 { |
| 567 for (var name in record) { | 257 for (var name in record) { |
| 568 var value = record[name]; | 258 var value = record[name]; |
| 569 if (typeof value !== "string") | 259 if (typeof value !== "string") |
| 570 continue; | 260 continue; |
| 571 | 261 |
| 572 var interned = this._stringPool[value]; | 262 var interned = this._stringPool[value]; |
| 573 if (typeof interned === "string") | 263 if (typeof interned === "string") |
| 574 record[name] = interned; | 264 record[name] = interned; |
| 575 else | 265 else |
| 576 this._stringPool[value] = value; | 266 this._stringPool[value] = value; |
| 577 } | 267 } |
| 578 | 268 |
| 579 var children = record.children; | 269 var children = record.children; |
| 580 for (var i = 0; children && i < children.length; ++i) | 270 for (var i = 0; children && i < children.length; ++i) |
| 581 this._internStrings(children[i]); | 271 this._internStrings(children[i]); |
| 582 }, | 272 }, |
| 583 | 273 |
| 584 __proto__: WebInspector.Object.prototype | 274 __proto__: WebInspector.TimelineModel.prototype |
| 585 } | 275 } |
| 586 | 276 |
| 587 | 277 |
| 588 /** | 278 /** |
| 589 * @constructor | 279 * @constructor |
| 590 */ | 280 */ |
| 591 WebInspector.TimelineModel.InterRecordBindings = function() { | 281 WebInspector.TimelineModelImpl.InterRecordBindings = function() { |
| 592 this._reset(); | 282 this._reset(); |
| 593 } | 283 } |
| 594 | 284 |
| 595 WebInspector.TimelineModel.InterRecordBindings.prototype = { | 285 WebInspector.TimelineModelImpl.InterRecordBindings.prototype = { |
| 596 _reset: function() | 286 _reset: function() |
| 597 { | 287 { |
| 598 this._sendRequestRecords = {}; | 288 this._sendRequestRecords = {}; |
| 599 this._timerRecords = {}; | 289 this._timerRecords = {}; |
| 600 this._requestAnimationFrameRecords = {}; | 290 this._requestAnimationFrameRecords = {}; |
| 601 this._layoutInvalidate = {}; | 291 this._layoutInvalidate = {}; |
| 602 this._lastScheduleStyleRecalculation = {}; | 292 this._lastScheduleStyleRecalculation = {}; |
| 603 this._webSocketCreateRecords = {}; | 293 this._webSocketCreateRecords = {}; |
| 604 } | 294 } |
| 605 } | 295 } |
| 606 | 296 |
| 607 /** | 297 /** |
| 608 * @interface | |
| 609 */ | |
| 610 WebInspector.TimelineModel.Record = function() | |
| 611 { | |
| 612 } | |
| 613 | |
| 614 WebInspector.TimelineModel.Record.prototype = { | |
| 615 /** | |
| 616 * @return {?Array.<!ConsoleAgent.CallFrame>} | |
| 617 */ | |
| 618 callSiteStackTrace: function() { }, | |
| 619 | |
| 620 /** | |
| 621 * @return {?WebInspector.TimelineModel.Record} | |
| 622 */ | |
| 623 initiator: function() { }, | |
| 624 | |
| 625 /** | |
| 626 * @return {!WebInspector.Target} | |
| 627 */ | |
| 628 target: function() { }, | |
| 629 | |
| 630 /** | |
| 631 * @return {number} | |
| 632 */ | |
| 633 selfTime: function() { }, | |
| 634 | |
| 635 /** | |
| 636 * @return {!Array.<!WebInspector.TimelineModel.Record>} | |
| 637 */ | |
| 638 children: function() { }, | |
| 639 | |
| 640 /** | |
| 641 * @return {!WebInspector.TimelineCategory} | |
| 642 */ | |
| 643 category: function() { }, | |
| 644 | |
| 645 /** | |
| 646 * @return {string} | |
| 647 */ | |
| 648 title: function() { }, | |
| 649 | |
| 650 /** | |
| 651 * @return {number} | |
| 652 */ | |
| 653 startTime: function() { }, | |
| 654 | |
| 655 /** | |
| 656 * @return {string|undefined} | |
| 657 */ | |
| 658 thread: function() { }, | |
| 659 | |
| 660 /** | |
| 661 * @return {number} | |
| 662 */ | |
| 663 endTime: function() { }, | |
| 664 | |
| 665 /** | |
| 666 * @param {number} endTime | |
| 667 */ | |
| 668 setEndTime: function(endTime) { }, | |
| 669 | |
| 670 /** | |
| 671 * @return {!Object} | |
| 672 */ | |
| 673 data: function() { }, | |
| 674 | |
| 675 /** | |
| 676 * @return {string} | |
| 677 */ | |
| 678 type: function() { }, | |
| 679 | |
| 680 /** | |
| 681 * @return {string} | |
| 682 */ | |
| 683 frameId: function() { }, | |
| 684 | |
| 685 /** | |
| 686 * @return {?Array.<!ConsoleAgent.CallFrame>} | |
| 687 */ | |
| 688 stackTrace: function() { }, | |
| 689 | |
| 690 /** | |
| 691 * @param {string} key | |
| 692 * @return {?Object} | |
| 693 */ | |
| 694 getUserObject: function(key) { }, | |
| 695 | |
| 696 /** | |
| 697 * @param {string} key | |
| 698 * @param {?Object|undefined} value | |
| 699 */ | |
| 700 setUserObject: function(key, value) { }, | |
| 701 | |
| 702 /** | |
| 703 * @return {!Object.<string, number>} | |
| 704 */ | |
| 705 aggregatedStats: function() { }, | |
| 706 | |
| 707 /** | |
| 708 * @return {?Array.<string>} | |
| 709 */ | |
| 710 warnings: function() { }, | |
| 711 | |
| 712 /** | |
| 713 * @param {!RegExp} regExp | |
| 714 * @return {boolean} | |
| 715 */ | |
| 716 testContentMatching: function(regExp) { } | |
| 717 } | |
| 718 | |
| 719 | |
| 720 /** | |
| 721 * @constructor | |
| 722 * @implements {WebInspector.TimelineModel.Record} | |
| 723 * @param {!WebInspector.TimelineModel} model | |
| 724 * @param {!WebInspector.TracingModel.Event} traceEvent | |
| 725 * @param {?WebInspector.TimelineModel.TraceEventRecord} parentRecord | |
| 726 */ | |
| 727 WebInspector.TimelineModel.TraceEventRecord = function(model, traceEvent, parent
Record) | |
| 728 { | |
| 729 this._model = model; | |
| 730 this._event = traceEvent; | |
| 731 traceEvent._timelineRecord = this; | |
| 732 if (parentRecord) { | |
| 733 this.parent = parentRecord; | |
| 734 parentRecord._children.push(this); | |
| 735 } | |
| 736 this._children = []; | |
| 737 } | |
| 738 | |
| 739 WebInspector.TimelineModel.TraceEventRecord.prototype = { | |
| 740 /** | |
| 741 * @return {?Array.<!ConsoleAgent.CallFrame>} | |
| 742 */ | |
| 743 callSiteStackTrace: function() | |
| 744 { | |
| 745 var initiator = this._event.initiator; | |
| 746 return initiator ? initiator.stackTrace : null; | |
| 747 }, | |
| 748 | |
| 749 /** | |
| 750 * @return {?WebInspector.TimelineModel.Record} | |
| 751 */ | |
| 752 initiator: function() | |
| 753 { | |
| 754 var initiator = this._event.initiator; | |
| 755 return initiator ? initiator._timelineRecord : null; | |
| 756 }, | |
| 757 | |
| 758 /** | |
| 759 * @return {!WebInspector.Target} | |
| 760 */ | |
| 761 target: function() | |
| 762 { | |
| 763 return this._model.target(); | |
| 764 }, | |
| 765 | |
| 766 /** | |
| 767 * @return {number} | |
| 768 */ | |
| 769 selfTime: function() | |
| 770 { | |
| 771 return this._event.selfTime / 1000; | |
| 772 }, | |
| 773 | |
| 774 /** | |
| 775 * @return {!Array.<!WebInspector.TimelineModel.Record>} | |
| 776 */ | |
| 777 children: function() | |
| 778 { | |
| 779 return this._children; | |
| 780 }, | |
| 781 | |
| 782 /** | |
| 783 * @return {!WebInspector.TimelineCategory} | |
| 784 */ | |
| 785 category: function() | |
| 786 { | |
| 787 var style = WebInspector.TimelineUIUtils.styleForTimelineEvent(this._eve
nt.name); | |
| 788 return style.category; | |
| 789 }, | |
| 790 | |
| 791 /** | |
| 792 * @return {string} | |
| 793 */ | |
| 794 title: function() | |
| 795 { | |
| 796 return WebInspector.TimelineUIUtils.recordTitle(this, this._model); | |
| 797 }, | |
| 798 | |
| 799 /** | |
| 800 * @return {number} | |
| 801 */ | |
| 802 startTime: function() | |
| 803 { | |
| 804 return this._event.startTime / 1000; | |
| 805 }, | |
| 806 | |
| 807 /** | |
| 808 * @return {string|undefined} | |
| 809 */ | |
| 810 thread: function() | |
| 811 { | |
| 812 return "CPU"; | |
| 813 }, | |
| 814 | |
| 815 /** | |
| 816 * @return {number} | |
| 817 */ | |
| 818 endTime: function() | |
| 819 { | |
| 820 return (this._event.endTime || this._event.startTime) / 1000; | |
| 821 }, | |
| 822 | |
| 823 /** | |
| 824 * @param {number} endTime | |
| 825 */ | |
| 826 setEndTime: function(endTime) | |
| 827 { | |
| 828 throw new Error("Unsupported operation setEndTime"); | |
| 829 }, | |
| 830 | |
| 831 /** | |
| 832 * @return {!Object} | |
| 833 */ | |
| 834 data: function() | |
| 835 { | |
| 836 return this._event.args.data; | |
| 837 }, | |
| 838 | |
| 839 /** | |
| 840 * @return {string} | |
| 841 */ | |
| 842 type: function() | |
| 843 { | |
| 844 return this._event.name; | |
| 845 }, | |
| 846 | |
| 847 /** | |
| 848 * @return {string} | |
| 849 */ | |
| 850 frameId: function() | |
| 851 { | |
| 852 switch (this._event.name) { | |
| 853 case WebInspector.TracingTimelineModel.RecordType.ScheduleStyleRecalcula
tion: | |
| 854 case WebInspector.TracingTimelineModel.RecordType.RecalculateStyles: | |
| 855 case WebInspector.TracingTimelineModel.RecordType.InvalidateLayout: | |
| 856 return this._event.args["frameId"]; | |
| 857 case WebInspector.TracingTimelineModel.RecordType.Layout: | |
| 858 return this._event.args["beginData"]["frameId"]; | |
| 859 default: | |
| 860 var data = this._event.args.data; | |
| 861 return (data && data["frame"]) || ""; | |
| 862 } | |
| 863 }, | |
| 864 | |
| 865 /** | |
| 866 * @return {?Array.<!ConsoleAgent.CallFrame>} | |
| 867 */ | |
| 868 stackTrace: function() | |
| 869 { | |
| 870 return this._event.stackTrace; | |
| 871 }, | |
| 872 | |
| 873 /** | |
| 874 * @param {string} key | |
| 875 * @return {?Object} | |
| 876 */ | |
| 877 getUserObject: function(key) | |
| 878 { | |
| 879 if (key === "TimelineUIUtils::preview-element") | |
| 880 return this._event.previewElement; | |
| 881 throw new Error("Unexpected key: " + key); | |
| 882 }, | |
| 883 | |
| 884 /** | |
| 885 * @param {string} key | |
| 886 * @param {?Object|undefined} value | |
| 887 */ | |
| 888 setUserObject: function(key, value) | |
| 889 { | |
| 890 if (key !== "TimelineUIUtils::preview-element") | |
| 891 throw new Error("Unexpected key: " + key); | |
| 892 this._event.previewElement = /** @type {?Element} */ (value); | |
| 893 }, | |
| 894 | |
| 895 /** | |
| 896 * @return {!Object.<string, number>} | |
| 897 */ | |
| 898 aggregatedStats: function() | |
| 899 { | |
| 900 return {}; | |
| 901 }, | |
| 902 | |
| 903 /** | |
| 904 * @return {?Array.<string>} | |
| 905 */ | |
| 906 warnings: function() | |
| 907 { | |
| 908 if (this._event.warning) | |
| 909 return [this._event.warning]; | |
| 910 return null; | |
| 911 }, | |
| 912 | |
| 913 /** | |
| 914 * @param {!RegExp} regExp | |
| 915 * @return {boolean} | |
| 916 */ | |
| 917 testContentMatching: function(regExp) | |
| 918 { | |
| 919 var tokens = [this.title()]; | |
| 920 var data = this._event.args.data; | |
| 921 if (data) { | |
| 922 for (var key in data) | |
| 923 tokens.push(data[key]); | |
| 924 } | |
| 925 return regExp.test(tokens.join("|")); | |
| 926 } | |
| 927 } | |
| 928 | |
| 929 /** | |
| 930 * @constructor | 298 * @constructor |
| 931 * @implements {WebInspector.TimelineModel.Record} | 299 * @implements {WebInspector.TimelineModel.Record} |
| 932 * @param {!WebInspector.TimelineModel} model | 300 * @param {!WebInspector.TimelineModel} model |
| 933 * @param {!TimelineAgent.TimelineEvent} timelineEvent | 301 * @param {!TimelineAgent.TimelineEvent} timelineEvent |
| 934 * @param {?WebInspector.TimelineModel.Record} parentRecord | 302 * @param {?WebInspector.TimelineModel.Record} parentRecord |
| 935 */ | 303 */ |
| 936 WebInspector.TimelineModel.RecordImpl = function(model, timelineEvent, parentRec
ord) | 304 WebInspector.TimelineModel.RecordImpl = function(model, timelineEvent, parentRec
ord) |
| 937 { | 305 { |
| 938 this._model = model; | 306 this._model = model; |
| 939 var bindings = this._model._bindings; | 307 var bindings = this._model._bindings; |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1203 { | 571 { |
| 1204 var tokens = [this.title()]; | 572 var tokens = [this.title()]; |
| 1205 for (var key in this._record.data) | 573 for (var key in this._record.data) |
| 1206 tokens.push(this._record.data[key]) | 574 tokens.push(this._record.data[key]) |
| 1207 return regExp.test(tokens.join("|")); | 575 return regExp.test(tokens.join("|")); |
| 1208 } | 576 } |
| 1209 } | 577 } |
| 1210 | 578 |
| 1211 /** | 579 /** |
| 1212 * @constructor | 580 * @constructor |
| 1213 */ | |
| 1214 WebInspector.TimelineModel.Filter = function() | |
| 1215 { | |
| 1216 /** @type {!WebInspector.TimelineModel} */ | |
| 1217 this._model; | |
| 1218 } | |
| 1219 | |
| 1220 WebInspector.TimelineModel.Filter.prototype = { | |
| 1221 /** | |
| 1222 * @param {!WebInspector.TimelineModel.Record} record | |
| 1223 * @return {boolean} | |
| 1224 */ | |
| 1225 accept: function(record) | |
| 1226 { | |
| 1227 return true; | |
| 1228 }, | |
| 1229 | |
| 1230 notifyFilterChanged: function() | |
| 1231 { | |
| 1232 this._model._filterChanged(); | |
| 1233 } | |
| 1234 } | |
| 1235 | |
| 1236 /** | |
| 1237 * @constructor | |
| 1238 * @implements {WebInspector.OutputStream} | 581 * @implements {WebInspector.OutputStream} |
| 1239 * @param {!WebInspector.TimelineModel} model | 582 * @param {!WebInspector.TimelineModel} model |
| 1240 * @param {!{cancel: function()}} reader | 583 * @param {!{cancel: function()}} reader |
| 1241 * @param {!WebInspector.Progress} progress | 584 * @param {!WebInspector.Progress} progress |
| 1242 */ | 585 */ |
| 1243 WebInspector.TimelineModelLoader = function(model, reader, progress) | 586 WebInspector.TimelineModelLoader = function(model, reader, progress) |
| 1244 { | 587 { |
| 1245 this._model = model; | 588 this._model = model; |
| 1246 this._reader = reader; | 589 this._reader = reader; |
| 1247 this._progress = progress; | 590 this._progress = progress; |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1402 } else { | 745 } else { |
| 1403 if (this._recordIndex === this._payloads.length) { | 746 if (this._recordIndex === this._payloads.length) { |
| 1404 stream.close(); | 747 stream.close(); |
| 1405 return; | 748 return; |
| 1406 } | 749 } |
| 1407 data.push(""); | 750 data.push(""); |
| 1408 } | 751 } |
| 1409 while (this._recordIndex < this._payloads.length) { | 752 while (this._recordIndex < this._payloads.length) { |
| 1410 var item = JSON.stringify(this._payloads[this._recordIndex]); | 753 var item = JSON.stringify(this._payloads[this._recordIndex]); |
| 1411 var itemLength = item.length + separator.length; | 754 var itemLength = item.length + separator.length; |
| 1412 if (length + itemLength > WebInspector.TimelineModel.TransferChunkLe
ngthBytes) | 755 if (length + itemLength > WebInspector.TimelineModelImpl.TransferChu
nkLengthBytes) |
| 1413 break; | 756 break; |
| 1414 length += itemLength; | 757 length += itemLength; |
| 1415 data.push(item); | 758 data.push(item); |
| 1416 ++this._recordIndex; | 759 ++this._recordIndex; |
| 1417 } | 760 } |
| 1418 if (this._recordIndex === this._payloads.length) | 761 if (this._recordIndex === this._payloads.length) |
| 1419 data.push(data.pop() + "]"); | 762 data.push(data.pop() + "]"); |
| 1420 stream.write(data.join(separator), this._writeNextChunk.bind(this)); | 763 stream.write(data.join(separator), this._writeNextChunk.bind(this)); |
| 1421 } | 764 } |
| 1422 } | 765 } |
| 1423 | |
| 1424 /** | |
| 1425 * @constructor | |
| 1426 */ | |
| 1427 WebInspector.TimelineMergingRecordBuffer = function() | |
| 1428 { | |
| 1429 this._backgroundRecordsBuffer = []; | |
| 1430 } | |
| 1431 | |
| 1432 /** | |
| 1433 * @constructor | |
| 1434 */ | |
| 1435 WebInspector.TimelineMergingRecordBuffer.prototype = { | |
| 1436 /** | |
| 1437 * @param {string} thread | |
| 1438 * @param {!Array.<!WebInspector.TimelineModel.Record>} records | |
| 1439 * @return {!Array.<!WebInspector.TimelineModel.Record>} | |
| 1440 */ | |
| 1441 process: function(thread, records) | |
| 1442 { | |
| 1443 if (thread) { | |
| 1444 this._backgroundRecordsBuffer = this._backgroundRecordsBuffer.concat
(records); | |
| 1445 return []; | |
| 1446 } | |
| 1447 /** | |
| 1448 * @param {!WebInspector.TimelineModel.Record} a | |
| 1449 * @param {!WebInspector.TimelineModel.Record} b | |
| 1450 */ | |
| 1451 function recordTimestampComparator(a, b) | |
| 1452 { | |
| 1453 // Never return 0, as the merge function will squash identical entri
es. | |
| 1454 return a.startTime() < b.startTime() ? -1 : 1; | |
| 1455 } | |
| 1456 var result = this._backgroundRecordsBuffer.mergeOrdered(records, recordT
imestampComparator); | |
| 1457 this._backgroundRecordsBuffer = []; | |
| 1458 return result; | |
| 1459 } | |
| 1460 } | |
| OLD | NEW |