| OLD | NEW |
| (Empty) |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * @constructor | |
| 7 * @extends {WebInspector.TimelineUIUtils} | |
| 8 */ | |
| 9 WebInspector.TimelineUIUtilsImpl = function() | |
| 10 { | |
| 11 WebInspector.TimelineUIUtils.call(this); | |
| 12 } | |
| 13 | |
| 14 WebInspector.TimelineUIUtilsImpl.prototype = { | |
| 15 /** | |
| 16 * @param {!WebInspector.TimelineModel.Record} record | |
| 17 * @return {boolean} | |
| 18 */ | |
| 19 isBeginFrame: function(record) | |
| 20 { | |
| 21 return record.type() === WebInspector.TimelineModel.RecordType.BeginFram
e; | |
| 22 }, | |
| 23 /** | |
| 24 * @param {!WebInspector.TimelineModel.Record} record | |
| 25 * @return {boolean} | |
| 26 */ | |
| 27 isProgram: function(record) | |
| 28 { | |
| 29 return record.type() === WebInspector.TimelineModel.RecordType.Program; | |
| 30 }, | |
| 31 /** | |
| 32 * @param {string} recordType | |
| 33 * @return {boolean} | |
| 34 */ | |
| 35 isCoalescable: function(recordType) | |
| 36 { | |
| 37 return !!WebInspector.TimelineUIUtilsImpl._coalescableRecordTypes[record
Type]; | |
| 38 }, | |
| 39 | |
| 40 /** | |
| 41 * @param {!WebInspector.TimelineModel.Record} record | |
| 42 * @return {boolean} | |
| 43 */ | |
| 44 isEventDivider: function(record) | |
| 45 { | |
| 46 return WebInspector.TimelineUIUtilsImpl.isEventDivider(record); | |
| 47 }, | |
| 48 | |
| 49 /** | |
| 50 * @param {!WebInspector.TimelineModel.Record} record | |
| 51 * @return {?Object} | |
| 52 */ | |
| 53 countersForRecord: function(record) | |
| 54 { | |
| 55 return record.type() === WebInspector.TimelineModel.RecordType.UpdateCou
nters ? record.data() : null; | |
| 56 }, | |
| 57 | |
| 58 /** | |
| 59 * @param {!WebInspector.TimelineModel.Record} record | |
| 60 * @return {?Object} | |
| 61 */ | |
| 62 highlightQuadForRecord: function(record) | |
| 63 { | |
| 64 var recordTypes = WebInspector.TimelineModel.RecordType; | |
| 65 switch(record.type()) { | |
| 66 case recordTypes.Layout: | |
| 67 return record.data().root; | |
| 68 case recordTypes.Paint: | |
| 69 return record.data().clip; | |
| 70 default: | |
| 71 return null; | |
| 72 } | |
| 73 }, | |
| 74 | |
| 75 /** | |
| 76 * @param {!WebInspector.TimelineModel.Record} record | |
| 77 * @return {string} | |
| 78 */ | |
| 79 titleForRecord: function(record) | |
| 80 { | |
| 81 return WebInspector.TimelineUIUtilsImpl._recordTitle(record); | |
| 82 }, | |
| 83 | |
| 84 /** | |
| 85 * @param {!WebInspector.TimelineModel.Record} record | |
| 86 * @return {!WebInspector.TimelineCategory} | |
| 87 */ | |
| 88 categoryForRecord: function(record) | |
| 89 { | |
| 90 return WebInspector.TimelineUIUtilsImpl.recordStyle(record).category; | |
| 91 }, | |
| 92 | |
| 93 /** | |
| 94 * @param {!WebInspector.TimelineModel.Record} record | |
| 95 * @param {!WebInspector.Linkifier} linkifier | |
| 96 * @return {?Node} | |
| 97 */ | |
| 98 buildDetailsNode: function(record, linkifier) | |
| 99 { | |
| 100 return WebInspector.TimelineUIUtilsImpl.buildDetailsNode(record, linkifi
er); | |
| 101 }, | |
| 102 | |
| 103 /** | |
| 104 * @param {!WebInspector.TimelineModel.Record} record | |
| 105 * @param {!WebInspector.TimelineModel} model | |
| 106 * @param {!WebInspector.Linkifier} linkifier | |
| 107 * @param {function(!DocumentFragment)} callback | |
| 108 */ | |
| 109 generateDetailsContent: function(record, model, linkifier, callback) | |
| 110 { | |
| 111 WebInspector.TimelineUIUtilsImpl.generateDetailsContent(record, model, l
inkifier, callback); | |
| 112 }, | |
| 113 | |
| 114 /** | |
| 115 * @return {!Element} | |
| 116 */ | |
| 117 createBeginFrameDivider: function() | |
| 118 { | |
| 119 return this.createEventDivider(WebInspector.TimelineModel.RecordType.Beg
inFrame); | |
| 120 }, | |
| 121 | |
| 122 /** | |
| 123 * @param {string} recordType | |
| 124 * @param {string=} title | |
| 125 * @return {!Element} | |
| 126 */ | |
| 127 createEventDivider: function(recordType, title) | |
| 128 { | |
| 129 return WebInspector.TimelineUIUtilsImpl._createEventDivider(recordType,
title); | |
| 130 }, | |
| 131 | |
| 132 /** | |
| 133 * @param {!WebInspector.TimelineModel.Record} record | |
| 134 * @param {!RegExp} regExp | |
| 135 * @return {boolean} | |
| 136 */ | |
| 137 testContentMatching: function(record, regExp) | |
| 138 { | |
| 139 var tokens = [WebInspector.TimelineUIUtilsImpl._recordTitle(record)]; | |
| 140 var data = record.data(); | |
| 141 for (var key in data) | |
| 142 tokens.push(data[key]) | |
| 143 return regExp.test(tokens.join("|")); | |
| 144 }, | |
| 145 | |
| 146 /** | |
| 147 * @param {!Object} total | |
| 148 * @param {!WebInspector.TimelineModel.Record} record | |
| 149 */ | |
| 150 aggregateTimeForRecord: function(total, record) | |
| 151 { | |
| 152 WebInspector.TimelineUIUtilsImpl.aggregateTimeForRecord(total, record); | |
| 153 }, | |
| 154 | |
| 155 /** | |
| 156 * @return {!WebInspector.TimelineModel.Filter} | |
| 157 */ | |
| 158 hiddenRecordsFilter: function() | |
| 159 { | |
| 160 var recordTypes = WebInspector.TimelineModel.RecordType; | |
| 161 var hiddenRecords = [ | |
| 162 recordTypes.ActivateLayerTree, | |
| 163 recordTypes.BeginFrame, | |
| 164 recordTypes.DrawFrame, | |
| 165 recordTypes.GPUTask, | |
| 166 recordTypes.InvalidateLayout, | |
| 167 recordTypes.MarkDOMContent, | |
| 168 recordTypes.MarkFirstPaint, | |
| 169 recordTypes.MarkLoad, | |
| 170 recordTypes.RequestMainThreadFrame, | |
| 171 recordTypes.ScheduleStyleRecalculation, | |
| 172 recordTypes.UpdateCounters | |
| 173 ]; | |
| 174 return new WebInspector.TimelineRecordHiddenTypeFilter(hiddenRecords); | |
| 175 }, | |
| 176 | |
| 177 __proto__: WebInspector.TimelineUIUtils.prototype | |
| 178 } | |
| 179 | |
| 180 | |
| 181 WebInspector.TimelineUIUtilsImpl._coalescableRecordTypes = {}; | |
| 182 WebInspector.TimelineUIUtilsImpl._coalescableRecordTypes[WebInspector.TimelineMo
del.RecordType.Layout] = 1; | |
| 183 WebInspector.TimelineUIUtilsImpl._coalescableRecordTypes[WebInspector.TimelineMo
del.RecordType.Paint] = 1; | |
| 184 WebInspector.TimelineUIUtilsImpl._coalescableRecordTypes[WebInspector.TimelineMo
del.RecordType.Rasterize] = 1; | |
| 185 WebInspector.TimelineUIUtilsImpl._coalescableRecordTypes[WebInspector.TimelineMo
del.RecordType.DecodeImage] = 1; | |
| 186 WebInspector.TimelineUIUtilsImpl._coalescableRecordTypes[WebInspector.TimelineMo
del.RecordType.ResizeImage] = 1; | |
| 187 | |
| 188 /** | |
| 189 * @return {!Object.<string, !{title: string, category: !WebInspector.TimelineCa
tegory}>} | |
| 190 */ | |
| 191 WebInspector.TimelineUIUtils._initRecordStyles = function() | |
| 192 { | |
| 193 if (WebInspector.TimelineUIUtils._recordStylesMap) | |
| 194 return WebInspector.TimelineUIUtils._recordStylesMap; | |
| 195 | |
| 196 var recordTypes = WebInspector.TimelineModel.RecordType; | |
| 197 var categories = WebInspector.TimelineUIUtils.categories(); | |
| 198 | |
| 199 var recordStyles = {}; | |
| 200 recordStyles[recordTypes.Root] = { title: "#root", category: categories["loa
ding"] }; | |
| 201 recordStyles[recordTypes.Program] = { title: WebInspector.UIString("Other"),
category: categories["other"] }; | |
| 202 recordStyles[recordTypes.EventDispatch] = { title: WebInspector.UIString("Ev
ent"), category: categories["scripting"] }; | |
| 203 recordStyles[recordTypes.BeginFrame] = { title: WebInspector.UIString("Frame
Start"), category: categories["rendering"] }; | |
| 204 recordStyles[recordTypes.ScheduleStyleRecalculation] = { title: WebInspector
.UIString("Schedule Style Recalculation"), category: categories["rendering"] }; | |
| 205 recordStyles[recordTypes.RecalculateStyles] = { title: WebInspector.UIString
("Recalculate Style"), category: categories["rendering"] }; | |
| 206 recordStyles[recordTypes.InvalidateLayout] = { title: WebInspector.UIString(
"Invalidate Layout"), category: categories["rendering"] }; | |
| 207 recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"),
category: categories["rendering"] }; | |
| 208 recordStyles[recordTypes.UpdateLayerTree] = { title: WebInspector.UIString("
Update Layer Tree"), category: categories["rendering"] }; | |
| 209 recordStyles[recordTypes.PaintSetup] = { title: WebInspector.UIString("Paint
Setup"), category: categories["painting"] }; | |
| 210 recordStyles[recordTypes.Paint] = { title: WebInspector.UIString("Paint"), c
ategory: categories["painting"] }; | |
| 211 recordStyles[recordTypes.Rasterize] = { title: WebInspector.UIString("Paint"
), category: categories["painting"] }; | |
| 212 recordStyles[recordTypes.ScrollLayer] = { title: WebInspector.UIString("Scro
ll"), category: categories["rendering"] }; | |
| 213 recordStyles[recordTypes.DecodeImage] = { title: WebInspector.UIString("Imag
e Decode"), category: categories["painting"] }; | |
| 214 recordStyles[recordTypes.ResizeImage] = { title: WebInspector.UIString("Imag
e Resize"), category: categories["painting"] }; | |
| 215 recordStyles[recordTypes.CompositeLayers] = { title: WebInspector.UIString("
Composite Layers"), category: categories["painting"] }; | |
| 216 recordStyles[recordTypes.ParseHTML] = { title: WebInspector.UIString("Parse
HTML"), category: categories["loading"] }; | |
| 217 recordStyles[recordTypes.TimerInstall] = { title: WebInspector.UIString("Ins
tall Timer"), category: categories["scripting"] }; | |
| 218 recordStyles[recordTypes.TimerRemove] = { title: WebInspector.UIString("Remo
ve Timer"), category: categories["scripting"] }; | |
| 219 recordStyles[recordTypes.TimerFire] = { title: WebInspector.UIString("Timer
Fired"), category: categories["scripting"] }; | |
| 220 recordStyles[recordTypes.XHRReadyStateChange] = { title: WebInspector.UIStri
ng("XHR Ready State Change"), category: categories["scripting"] }; | |
| 221 recordStyles[recordTypes.XHRLoad] = { title: WebInspector.UIString("XHR Load
"), category: categories["scripting"] }; | |
| 222 recordStyles[recordTypes.EvaluateScript] = { title: WebInspector.UIString("E
valuate Script"), category: categories["scripting"] }; | |
| 223 recordStyles[recordTypes.ResourceSendRequest] = { title: WebInspector.UIStri
ng("Send Request"), category: categories["loading"] }; | |
| 224 recordStyles[recordTypes.ResourceReceiveResponse] = { title: WebInspector.UI
String("Receive Response"), category: categories["loading"] }; | |
| 225 recordStyles[recordTypes.ResourceFinish] = { title: WebInspector.UIString("F
inish Loading"), category: categories["loading"] }; | |
| 226 recordStyles[recordTypes.FunctionCall] = { title: WebInspector.UIString("Fun
ction Call"), category: categories["scripting"] }; | |
| 227 recordStyles[recordTypes.ResourceReceivedData] = { title: WebInspector.UIStr
ing("Receive Data"), category: categories["loading"] }; | |
| 228 recordStyles[recordTypes.GCEvent] = { title: WebInspector.UIString("GC Event
"), category: categories["scripting"] }; | |
| 229 recordStyles[recordTypes.MarkDOMContent] = { title: WebInspector.UIString("D
OMContentLoaded event"), category: categories["scripting"] }; | |
| 230 recordStyles[recordTypes.MarkLoad] = { title: WebInspector.UIString("Load ev
ent"), category: categories["scripting"] }; | |
| 231 recordStyles[recordTypes.MarkFirstPaint] = { title: WebInspector.UIString("F
irst paint"), category: categories["painting"] }; | |
| 232 recordStyles[recordTypes.TimeStamp] = { title: WebInspector.UIString("Timest
amp"), category: categories["scripting"] }; | |
| 233 recordStyles[recordTypes.ConsoleTime] = { title: WebInspector.UIString("Cons
ole Time"), category: categories["scripting"] }; | |
| 234 recordStyles[recordTypes.RequestAnimationFrame] = { title: WebInspector.UISt
ring("Request Animation Frame"), category: categories["scripting"] }; | |
| 235 recordStyles[recordTypes.CancelAnimationFrame] = { title: WebInspector.UIStr
ing("Cancel Animation Frame"), category: categories["scripting"] }; | |
| 236 recordStyles[recordTypes.FireAnimationFrame] = { title: WebInspector.UIStrin
g("Animation Frame Fired"), category: categories["scripting"] }; | |
| 237 recordStyles[recordTypes.WebSocketCreate] = { title: WebInspector.UIString("
Create WebSocket"), category: categories["scripting"] }; | |
| 238 recordStyles[recordTypes.WebSocketSendHandshakeRequest] = { title: WebInspec
tor.UIString("Send WebSocket Handshake"), category: categories["scripting"] }; | |
| 239 recordStyles[recordTypes.WebSocketReceiveHandshakeResponse] = { title: WebIn
spector.UIString("Receive WebSocket Handshake"), category: categories["scripting
"] }; | |
| 240 recordStyles[recordTypes.WebSocketDestroy] = { title: WebInspector.UIString(
"Destroy WebSocket"), category: categories["scripting"] }; | |
| 241 recordStyles[recordTypes.EmbedderCallback] = { title: WebInspector.UIString(
"Embedder Callback"), category: categories["scripting"] }; | |
| 242 | |
| 243 WebInspector.TimelineUIUtils._recordStylesMap = recordStyles; | |
| 244 return recordStyles; | |
| 245 } | |
| 246 | |
| 247 /** | |
| 248 * @param {!WebInspector.TimelineModel.Record} record | |
| 249 * @return {!{title: string, category: !WebInspector.TimelineCategory}} | |
| 250 */ | |
| 251 WebInspector.TimelineUIUtilsImpl.recordStyle = function(record) | |
| 252 { | |
| 253 var type = record.type(); | |
| 254 var recordStyles = WebInspector.TimelineUIUtils._initRecordStyles(); | |
| 255 var result = recordStyles[type]; | |
| 256 if (!result) { | |
| 257 result = { | |
| 258 title: WebInspector.UIString("Unknown: %s", type), | |
| 259 category: WebInspector.TimelineUIUtils.categories()["other"] | |
| 260 }; | |
| 261 recordStyles[type] = result; | |
| 262 } | |
| 263 return result; | |
| 264 } | |
| 265 | |
| 266 /** | |
| 267 * @param {!WebInspector.TimelineModel.Record} record | |
| 268 * @return {string} | |
| 269 */ | |
| 270 WebInspector.TimelineUIUtilsImpl._recordTitle = function(record) | |
| 271 { | |
| 272 var recordData = record.data(); | |
| 273 var title = WebInspector.TimelineUIUtilsImpl.recordStyle(record).title; | |
| 274 if (record.type() === WebInspector.TimelineModel.RecordType.TimeStamp || rec
ord.type() === WebInspector.TimelineModel.RecordType.ConsoleTime) | |
| 275 return WebInspector.UIString("%s: %s", title, recordData["message"]); | |
| 276 if (WebInspector.TimelineUIUtilsImpl.isEventDivider(record)) { | |
| 277 var startTime = Number.millisToString(record.startTime() - record._model
.minimumRecordTime()); | |
| 278 return WebInspector.UIString("%s at %s", title, startTime); | |
| 279 } | |
| 280 return title; | |
| 281 } | |
| 282 | |
| 283 /** | |
| 284 * @param {!WebInspector.TimelineModel.Record} record | |
| 285 * @return {boolean} | |
| 286 */ | |
| 287 WebInspector.TimelineUIUtilsImpl.isEventDivider = function(record) | |
| 288 { | |
| 289 var recordTypes = WebInspector.TimelineModel.RecordType; | |
| 290 if (record.type() === recordTypes.TimeStamp) | |
| 291 return true; | |
| 292 if (record.type() === recordTypes.MarkFirstPaint) | |
| 293 return true; | |
| 294 if (record.type() === recordTypes.MarkDOMContent || record.type() === record
Types.MarkLoad) | |
| 295 return record.data()["isMainFrame"]; | |
| 296 return false; | |
| 297 } | |
| 298 | |
| 299 /** | |
| 300 * @param {!Object} total | |
| 301 * @param {!WebInspector.TimelineModel.Record} record | |
| 302 */ | |
| 303 WebInspector.TimelineUIUtilsImpl.aggregateTimeForRecord = function(total, record
) | |
| 304 { | |
| 305 var children = record.children(); | |
| 306 for (var i = 0; i < children.length; ++i) | |
| 307 WebInspector.TimelineUIUtilsImpl.aggregateTimeForRecord(total, children[
i]); | |
| 308 var categoryName = WebInspector.TimelineUIUtilsImpl.recordStyle(record).cate
gory.name; | |
| 309 total[categoryName] = (total[categoryName] || 0) + record.selfTime(); | |
| 310 } | |
| 311 | |
| 312 /** | |
| 313 * @param {!WebInspector.TimelineModel.Record} record | |
| 314 * @param {!WebInspector.Linkifier} linkifier | |
| 315 * @return {?Node} | |
| 316 */ | |
| 317 WebInspector.TimelineUIUtilsImpl.buildDetailsNode = function(record, linkifier) | |
| 318 { | |
| 319 var details; | |
| 320 var detailsText; | |
| 321 var recordData = record.data(); | |
| 322 switch (record.type()) { | |
| 323 case WebInspector.TimelineModel.RecordType.GCEvent: | |
| 324 detailsText = WebInspector.UIString("%s collected", Number.bytesToString
(recordData["usedHeapSizeDelta"])); | |
| 325 break; | |
| 326 case WebInspector.TimelineModel.RecordType.TimerFire: | |
| 327 detailsText = recordData["timerId"]; | |
| 328 break; | |
| 329 case WebInspector.TimelineModel.RecordType.FunctionCall: | |
| 330 details = linkifyLocation(recordData["scriptId"], recordData["scriptName
"], recordData["scriptLine"], 0); | |
| 331 break; | |
| 332 case WebInspector.TimelineModel.RecordType.FireAnimationFrame: | |
| 333 detailsText = recordData["id"]; | |
| 334 break; | |
| 335 case WebInspector.TimelineModel.RecordType.EventDispatch: | |
| 336 detailsText = recordData ? recordData["type"] : null; | |
| 337 break; | |
| 338 case WebInspector.TimelineModel.RecordType.Paint: | |
| 339 var width = WebInspector.TimelineUIUtils.quadWidth(recordData.clip); | |
| 340 var height = WebInspector.TimelineUIUtils.quadHeight(recordData.clip); | |
| 341 if (width && height) | |
| 342 detailsText = WebInspector.UIString("%d\u2009\u00d7\u2009%d", width,
height); | |
| 343 break; | |
| 344 case WebInspector.TimelineModel.RecordType.TimerInstall: | |
| 345 case WebInspector.TimelineModel.RecordType.TimerRemove: | |
| 346 details = linkifyTopCallFrame(); | |
| 347 detailsText = recordData["timerId"]; | |
| 348 break; | |
| 349 case WebInspector.TimelineModel.RecordType.RequestAnimationFrame: | |
| 350 case WebInspector.TimelineModel.RecordType.CancelAnimationFrame: | |
| 351 details = linkifyTopCallFrame(); | |
| 352 detailsText = recordData["id"]; | |
| 353 break; | |
| 354 case WebInspector.TimelineModel.RecordType.ParseHTML: | |
| 355 case WebInspector.TimelineModel.RecordType.RecalculateStyles: | |
| 356 details = linkifyTopCallFrame(); | |
| 357 break; | |
| 358 case WebInspector.TimelineModel.RecordType.EvaluateScript: | |
| 359 var url = recordData["url"]; | |
| 360 if (url) | |
| 361 details = linkifyLocation("", url, recordData["lineNumber"], 0); | |
| 362 break; | |
| 363 case WebInspector.TimelineModel.RecordType.XHRReadyStateChange: | |
| 364 case WebInspector.TimelineModel.RecordType.XHRLoad: | |
| 365 case WebInspector.TimelineModel.RecordType.ResourceSendRequest: | |
| 366 case WebInspector.TimelineModel.RecordType.DecodeImage: | |
| 367 case WebInspector.TimelineModel.RecordType.ResizeImage: | |
| 368 var url = recordData["url"]; | |
| 369 if (url) | |
| 370 detailsText = WebInspector.displayNameForURL(url); | |
| 371 break; | |
| 372 case WebInspector.TimelineModel.RecordType.ResourceReceivedData: | |
| 373 case WebInspector.TimelineModel.RecordType.ResourceReceiveResponse: | |
| 374 case WebInspector.TimelineModel.RecordType.ResourceFinish: | |
| 375 var initiator = record.initiator(); | |
| 376 if (initiator) { | |
| 377 var url = initiator.data()["url"]; | |
| 378 if (url) | |
| 379 detailsText = WebInspector.displayNameForURL(url); | |
| 380 } | |
| 381 break; | |
| 382 case WebInspector.TimelineModel.RecordType.ConsoleTime: | |
| 383 detailsText = recordData["message"]; | |
| 384 break; | |
| 385 case WebInspector.TimelineModel.RecordType.EmbedderCallback: | |
| 386 detailsText = recordData["callbackName"]; | |
| 387 break; | |
| 388 default: | |
| 389 details = linkifyTopCallFrame(); | |
| 390 break; | |
| 391 } | |
| 392 | |
| 393 if (!details && detailsText) | |
| 394 details = createTextNode(detailsText); | |
| 395 return details; | |
| 396 | |
| 397 /** | |
| 398 * @param {string} scriptId | |
| 399 * @param {string} url | |
| 400 * @param {number} lineNumber | |
| 401 * @param {number=} columnNumber | |
| 402 */ | |
| 403 function linkifyLocation(scriptId, url, lineNumber, columnNumber) | |
| 404 { | |
| 405 if (!url) | |
| 406 return null; | |
| 407 | |
| 408 // FIXME(62725): stack trace line/column numbers are one-based. | |
| 409 columnNumber = columnNumber ? columnNumber - 1 : 0; | |
| 410 return linkifier.linkifyScriptLocation(record.target(), scriptId, url, l
ineNumber - 1, columnNumber, "timeline-details"); | |
| 411 } | |
| 412 | |
| 413 /** | |
| 414 * @return {?Element} | |
| 415 */ | |
| 416 function linkifyTopCallFrame() | |
| 417 { | |
| 418 if (record.stackTrace()) | |
| 419 return linkifier.linkifyConsoleCallFrame(record.target(), record.sta
ckTrace()[0], "timeline-details"); | |
| 420 if (record.callSiteStackTrace()) | |
| 421 return linkifier.linkifyConsoleCallFrame(record.target(), record.cal
lSiteStackTrace()[0], "timeline-details"); | |
| 422 return null; | |
| 423 } | |
| 424 } | |
| 425 | |
| 426 /** | |
| 427 * @param {string=} recordType | |
| 428 * @return {boolean} | |
| 429 */ | |
| 430 WebInspector.TimelineUIUtilsImpl._needsPreviewElement = function(recordType) | |
| 431 { | |
| 432 if (!recordType) | |
| 433 return false; | |
| 434 const recordTypes = WebInspector.TimelineModel.RecordType; | |
| 435 switch (recordType) { | |
| 436 case recordTypes.ResourceSendRequest: | |
| 437 case recordTypes.ResourceReceiveResponse: | |
| 438 case recordTypes.ResourceReceivedData: | |
| 439 case recordTypes.ResourceFinish: | |
| 440 return true; | |
| 441 default: | |
| 442 return false; | |
| 443 } | |
| 444 } | |
| 445 | |
| 446 /** | |
| 447 * @param {!WebInspector.TimelineModel.Record} record | |
| 448 * @param {!WebInspector.TimelineModel} model | |
| 449 * @param {!WebInspector.Linkifier} linkifier | |
| 450 * @param {function(!DocumentFragment)} callback | |
| 451 */ | |
| 452 WebInspector.TimelineUIUtilsImpl.generateDetailsContent = function(record, model
, linkifier, callback) | |
| 453 { | |
| 454 var imageElement = /** @type {?Element} */ (record.getUserObject("TimelineUI
Utils::preview-element") || null); | |
| 455 var relatedNode = null; | |
| 456 var recordData = record.data(); | |
| 457 var barrier = new CallbackBarrier(); | |
| 458 var target = record.target(); | |
| 459 if (!imageElement && WebInspector.TimelineUIUtilsImpl._needsPreviewElement(r
ecord.type()) && target) | |
| 460 WebInspector.DOMPresentationUtils.buildImagePreviewContents(target, reco
rdData["url"], false, barrier.createCallback(saveImage)); | |
| 461 if (recordData["backendNodeId"] && target) | |
| 462 target.domModel.pushNodesByBackendIdsToFrontend([recordData["backendNode
Id"]], barrier.createCallback(setRelatedNode)); | |
| 463 barrier.callWhenDone(callbackWrapper); | |
| 464 | |
| 465 /** | |
| 466 * @param {!Element=} element | |
| 467 */ | |
| 468 function saveImage(element) | |
| 469 { | |
| 470 imageElement = element || null; | |
| 471 record.setUserObject("TimelineUIUtils::preview-element", element); | |
| 472 } | |
| 473 | |
| 474 /** | |
| 475 * @param {?Array.<!DOMAgent.NodeId>} nodeIds | |
| 476 */ | |
| 477 function setRelatedNode(nodeIds) | |
| 478 { | |
| 479 if (nodeIds && target) | |
| 480 relatedNode = target.domModel.nodeForId(nodeIds[0]); | |
| 481 } | |
| 482 | |
| 483 function callbackWrapper() | |
| 484 { | |
| 485 callback(WebInspector.TimelineUIUtilsImpl._generateDetailsContentSynchro
nously(record, model, linkifier, imageElement, relatedNode)); | |
| 486 } | |
| 487 } | |
| 488 | |
| 489 /** | |
| 490 * @param {!WebInspector.TimelineModel.Record} record | |
| 491 * @param {!WebInspector.TimelineModel} model | |
| 492 * @param {!WebInspector.Linkifier} linkifier | |
| 493 * @param {?Element} imagePreviewElement | |
| 494 * @param {?WebInspector.DOMNode} relatedNode | |
| 495 * @return {!DocumentFragment} | |
| 496 */ | |
| 497 WebInspector.TimelineUIUtilsImpl._generateDetailsContentSynchronously = function
(record, model, linkifier, imagePreviewElement, relatedNode) | |
| 498 { | |
| 499 var fragment = createDocumentFragment(); | |
| 500 const recordTypes = WebInspector.TimelineModel.RecordType; | |
| 501 | |
| 502 // The messages may vary per record.type(); | |
| 503 var callSiteStackTraceLabel; | |
| 504 var callStackLabel; | |
| 505 var relatedNodeLabel; | |
| 506 | |
| 507 var contentHelper = new WebInspector.TimelineDetailsContentHelper(record.tar
get(), linkifier, true); | |
| 508 contentHelper.appendTextRow(WebInspector.UIString("Self Time"), Number.milli
sToString(record.selfTime(), true)); | |
| 509 contentHelper.appendTextRow(WebInspector.UIString("Start Time"), Number.mill
isToString(record.startTime() - model.minimumRecordTime())); | |
| 510 var recordData = record.data(); | |
| 511 | |
| 512 switch (record.type()) { | |
| 513 case recordTypes.GCEvent: | |
| 514 contentHelper.appendTextRow(WebInspector.UIString("Collected"), Numb
er.bytesToString(recordData["usedHeapSizeDelta"])); | |
| 515 break; | |
| 516 case recordTypes.TimerFire: | |
| 517 callSiteStackTraceLabel = WebInspector.UIString("Timer installed"); | |
| 518 // Fall-through intended. | |
| 519 | |
| 520 case recordTypes.TimerInstall: | |
| 521 case recordTypes.TimerRemove: | |
| 522 contentHelper.appendTextRow(WebInspector.UIString("Timer ID"), recor
dData["timerId"]); | |
| 523 if (record.type() === recordTypes.TimerInstall) { | |
| 524 contentHelper.appendTextRow(WebInspector.UIString("Timeout"), Nu
mber.millisToString(recordData["timeout"])); | |
| 525 contentHelper.appendTextRow(WebInspector.UIString("Repeats"), !r
ecordData["singleShot"]); | |
| 526 } | |
| 527 break; | |
| 528 case recordTypes.FireAnimationFrame: | |
| 529 callSiteStackTraceLabel = WebInspector.UIString("Animation frame req
uested"); | |
| 530 contentHelper.appendTextRow(WebInspector.UIString("Callback ID"), re
cordData["id"]); | |
| 531 break; | |
| 532 case recordTypes.FunctionCall: | |
| 533 if (recordData["scriptName"]) | |
| 534 contentHelper.appendLocationRow(WebInspector.UIString("Location"
), recordData["scriptName"], recordData["scriptLine"]); | |
| 535 break; | |
| 536 case recordTypes.ResourceSendRequest: | |
| 537 case recordTypes.ResourceReceiveResponse: | |
| 538 case recordTypes.ResourceReceivedData: | |
| 539 case recordTypes.ResourceFinish: | |
| 540 var url; | |
| 541 if (record.type() === recordTypes.ResourceSendRequest) | |
| 542 url = recordData["url"]; | |
| 543 else if (record.initiator()) | |
| 544 url = record.initiator().data()["url"]; | |
| 545 if (url) | |
| 546 contentHelper.appendElementRow(WebInspector.UIString("Resource")
, WebInspector.linkifyResourceAsNode(url)); | |
| 547 if (imagePreviewElement) | |
| 548 contentHelper.appendElementRow(WebInspector.UIString("Preview"),
imagePreviewElement); | |
| 549 if (recordData["requestMethod"]) | |
| 550 contentHelper.appendTextRow(WebInspector.UIString("Request Metho
d"), recordData["requestMethod"]); | |
| 551 if (typeof recordData["statusCode"] === "number") | |
| 552 contentHelper.appendTextRow(WebInspector.UIString("Status Code")
, recordData["statusCode"]); | |
| 553 if (recordData["mimeType"]) | |
| 554 contentHelper.appendTextRow(WebInspector.UIString("MIME Type"),
recordData["mimeType"]); | |
| 555 if (recordData["encodedDataLength"]) | |
| 556 contentHelper.appendTextRow(WebInspector.UIString("Encoded Data
Length"), WebInspector.UIString("%d Bytes", recordData["encodedDataLength"])); | |
| 557 break; | |
| 558 case recordTypes.EvaluateScript: | |
| 559 var url = recordData["url"]; | |
| 560 if (url) | |
| 561 contentHelper.appendLocationRow(WebInspector.UIString("Script"),
url, recordData["lineNumber"]); | |
| 562 break; | |
| 563 case recordTypes.Paint: | |
| 564 var clip = recordData["clip"]; | |
| 565 contentHelper.appendTextRow(WebInspector.UIString("Location"), WebIn
spector.UIString("(%d, %d)", clip[0], clip[1])); | |
| 566 var clipWidth = WebInspector.TimelineUIUtils.quadWidth(clip); | |
| 567 var clipHeight = WebInspector.TimelineUIUtils.quadHeight(clip); | |
| 568 contentHelper.appendTextRow(WebInspector.UIString("Dimensions"), Web
Inspector.UIString("%d × %d", clipWidth, clipHeight)); | |
| 569 // Fall-through intended. | |
| 570 | |
| 571 case recordTypes.PaintSetup: | |
| 572 case recordTypes.Rasterize: | |
| 573 case recordTypes.ScrollLayer: | |
| 574 relatedNodeLabel = WebInspector.UIString("Layer root"); | |
| 575 break; | |
| 576 case recordTypes.DecodeImage: | |
| 577 case recordTypes.ResizeImage: | |
| 578 relatedNodeLabel = WebInspector.UIString("Image element"); | |
| 579 var url = recordData["url"]; | |
| 580 if (url) | |
| 581 contentHelper.appendElementRow(WebInspector.UIString("Image URL"
), WebInspector.linkifyResourceAsNode(url)); | |
| 582 break; | |
| 583 case recordTypes.RecalculateStyles: // We don't want to see default deta
ils. | |
| 584 if (recordData["elementCount"]) | |
| 585 contentHelper.appendTextRow(WebInspector.UIString("Elements affe
cted"), recordData["elementCount"]); | |
| 586 callStackLabel = WebInspector.UIString("Styles recalculation forced"
); | |
| 587 break; | |
| 588 case recordTypes.Layout: | |
| 589 if (recordData["dirtyObjects"]) | |
| 590 contentHelper.appendTextRow(WebInspector.UIString("Nodes that ne
ed layout"), recordData["dirtyObjects"]); | |
| 591 if (recordData["totalObjects"]) | |
| 592 contentHelper.appendTextRow(WebInspector.UIString("Layout tree s
ize"), recordData["totalObjects"]); | |
| 593 if (typeof recordData["partialLayout"] === "boolean") { | |
| 594 contentHelper.appendTextRow(WebInspector.UIString("Layout scope"
), | |
| 595 recordData["partialLayout"] ? WebInspector.UIString("Partial"
) : WebInspector.UIString("Whole document")); | |
| 596 } | |
| 597 callSiteStackTraceLabel = WebInspector.UIString("Layout invalidated"
); | |
| 598 callStackLabel = WebInspector.UIString("Layout forced"); | |
| 599 relatedNodeLabel = WebInspector.UIString("Layout root"); | |
| 600 break; | |
| 601 case recordTypes.ConsoleTime: | |
| 602 contentHelper.appendTextRow(WebInspector.UIString("Message"), record
Data["message"]); | |
| 603 break; | |
| 604 case recordTypes.WebSocketCreate: | |
| 605 case recordTypes.WebSocketSendHandshakeRequest: | |
| 606 case recordTypes.WebSocketReceiveHandshakeResponse: | |
| 607 case recordTypes.WebSocketDestroy: | |
| 608 var initiatorData = record.initiator() ? record.initiator().data() :
recordData; | |
| 609 if (typeof initiatorData["webSocketURL"] !== "undefined") | |
| 610 contentHelper.appendTextRow(WebInspector.UIString("URL"), initia
torData["webSocketURL"]); | |
| 611 if (typeof initiatorData["webSocketProtocol"] !== "undefined") | |
| 612 contentHelper.appendTextRow(WebInspector.UIString("WebSocket Pro
tocol"), initiatorData["webSocketProtocol"]); | |
| 613 if (typeof recordData["message"] !== "undefined") | |
| 614 contentHelper.appendTextRow(WebInspector.UIString("Message"), re
cordData["message"]); | |
| 615 break; | |
| 616 case recordTypes.EmbedderCallback: | |
| 617 contentHelper.appendTextRow(WebInspector.UIString("Callback Function
"), recordData["callbackName"]); | |
| 618 break; | |
| 619 default: | |
| 620 var detailsNode = WebInspector.TimelineUIUtilsImpl.buildDetailsNode(
record, linkifier); | |
| 621 if (detailsNode) | |
| 622 contentHelper.appendElementRow(WebInspector.UIString("Details"),
detailsNode); | |
| 623 break; | |
| 624 } | |
| 625 | |
| 626 if (relatedNode) | |
| 627 contentHelper.appendElementRow(relatedNodeLabel || WebInspector.UIString
("Related node"), WebInspector.DOMPresentationUtils.linkifyNodeReference(related
Node)); | |
| 628 | |
| 629 if (recordData["scriptName"] && record.type() !== recordTypes.FunctionCall) | |
| 630 contentHelper.appendLocationRow(WebInspector.UIString("Function Call"),
recordData["scriptName"], recordData["scriptLine"]); | |
| 631 var callSiteStackTrace = record.callSiteStackTrace(); | |
| 632 if (callSiteStackTrace) | |
| 633 contentHelper.appendStackTrace(callSiteStackTraceLabel || WebInspector.U
IString("Call Site stack"), callSiteStackTrace); | |
| 634 var recordStackTrace = record.stackTrace(); | |
| 635 if (recordStackTrace) | |
| 636 contentHelper.appendStackTrace(callStackLabel || WebInspector.UIString("
Call Stack"), recordStackTrace); | |
| 637 | |
| 638 if (record.warnings()) { | |
| 639 var ul = createElement("ul"); | |
| 640 for (var i = 0; i < record.warnings().length; ++i) | |
| 641 ul.createChild("li").textContent = record.warnings()[i]; | |
| 642 contentHelper.appendElementRow(WebInspector.UIString("Warning"), ul); | |
| 643 } | |
| 644 fragment.appendChild(contentHelper.element); | |
| 645 | |
| 646 var aggregatedStats = {}; | |
| 647 WebInspector.TimelineUIUtilsImpl.aggregateTimeForRecord(aggregatedStats, rec
ord); | |
| 648 if (record.children().length) | |
| 649 fragment.appendChild(WebInspector.TimelineUIUtils.generatePieChart(aggre
gatedStats, WebInspector.TimelineUIUtilsImpl.recordStyle(record).category, recor
d.selfTime())); | |
| 650 else | |
| 651 fragment.appendChild(WebInspector.TimelineUIUtils.generatePieChart(aggre
gatedStats)); | |
| 652 | |
| 653 return fragment; | |
| 654 } | |
| 655 | |
| 656 /** | |
| 657 * @param {string} recordType | |
| 658 * @param {string=} title | |
| 659 * @return {!Element} | |
| 660 */ | |
| 661 WebInspector.TimelineUIUtilsImpl._createEventDivider = function(recordType, titl
e) | |
| 662 { | |
| 663 var eventDivider = createElement("div"); | |
| 664 eventDivider.className = "resources-event-divider"; | |
| 665 var recordTypes = WebInspector.TimelineModel.RecordType; | |
| 666 | |
| 667 if (recordType === recordTypes.MarkDOMContent) | |
| 668 eventDivider.className += " resources-blue-divider"; | |
| 669 else if (recordType === recordTypes.MarkLoad) | |
| 670 eventDivider.className += " resources-red-divider"; | |
| 671 else if (recordType === recordTypes.MarkFirstPaint) | |
| 672 eventDivider.className += " resources-green-divider"; | |
| 673 else if (recordType === recordTypes.TimeStamp) | |
| 674 eventDivider.className += " resources-orange-divider"; | |
| 675 else if (recordType === recordTypes.BeginFrame) | |
| 676 eventDivider.className += " timeline-frame-divider"; | |
| 677 | |
| 678 if (title) | |
| 679 eventDivider.title = title; | |
| 680 | |
| 681 return eventDivider; | |
| 682 } | |
| OLD | NEW |