Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: Source/devtools/front_end/timeline/TimelineModel.js

Issue 313333002: Extract implementation based on timeline events into TimelineModelImpl (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/devtools/devtools.gypi ('k') | Source/devtools/front_end/timeline/TimelineModelImpl.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 13 matching lines...) Expand all
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 /** 31 /**
32 * @constructor 32 * @constructor
33 * @extends {WebInspector.Object} 33 * @extends {WebInspector.Object}
34 * @param {!WebInspector.TimelineManager} timelineManager 34 * @param {!WebInspector.Target} target
35 */ 35 */
36 WebInspector.TimelineModel = function(timelineManager) 36 WebInspector.TimelineModel = function(target)
37 { 37 {
38 this._timelineManager = timelineManager;
39 this._filters = []; 38 this._filters = [];
40 this._bindings = new WebInspector.TimelineModel.InterRecordBindings(); 39 this._target = target;
41
42 this.reset();
43
44 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp es.TimelineEventRecorded, this._onRecordAdded, this);
45 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp es.TimelineStarted, this._onStarted, this);
46 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp es.TimelineStopped, this._onStopped, this);
47 this._timelineManager.addEventListener(WebInspector.TimelineManager.EventTyp es.TimelineProgress, this._onProgress, this);
48 } 40 }
49 41
50 WebInspector.TimelineModel.TransferChunkLengthBytes = 5000000;
51
52 WebInspector.TimelineModel.RecordType = { 42 WebInspector.TimelineModel.RecordType = {
53 Root: "Root", 43 Root: "Root",
54 Program: "Program", 44 Program: "Program",
55 EventDispatch: "EventDispatch", 45 EventDispatch: "EventDispatch",
56 46
57 GPUTask: "GPUTask", 47 GPUTask: "GPUTask",
58 48
59 RequestMainThreadFrame: "RequestMainThreadFrame", 49 RequestMainThreadFrame: "RequestMainThreadFrame",
60 BeginFrame: "BeginFrame", 50 BeginFrame: "BeginFrame",
61 ActivateLayerTree: "ActivateLayerTree", 51 ActivateLayerTree: "ActivateLayerTree",
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
150 } 140 }
151 return processRecords(recordsArray, 0); 141 return processRecords(recordsArray, 0);
152 } 142 }
153 143
154 WebInspector.TimelineModel.prototype = { 144 WebInspector.TimelineModel.prototype = {
155 /** 145 /**
156 * @return {!WebInspector.Target} 146 * @return {!WebInspector.Target}
157 */ 147 */
158 target: function() 148 target: function()
159 { 149 {
160 return this._timelineManager.target(); 150 return this._target;
161 }, 151 },
162 152
163 /** 153 /**
164 * @return {boolean} 154 * @return {boolean}
165 */ 155 */
166 loadedFromFile: function() 156 loadedFromFile: function()
167 { 157 {
168 return this._loadedFromFile; 158 return false;
169 }, 159 },
170 160
171 /** 161 /**
172 * @param {?function(!WebInspector.TimelineModel.Record)|?function(!WebInspe ctor.TimelineModel.Record,number)} preOrderCallback 162 * @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 163 * @param {function(!WebInspector.TimelineModel.Record)|function(!WebInspect or.TimelineModel.Record,number)=} postOrderCallback
174 */ 164 */
175 forAllRecords: function(preOrderCallback, postOrderCallback) 165 forAllRecords: function(preOrderCallback, postOrderCallback)
176 { 166 {
177 WebInspector.TimelineModel.forAllRecords(this._records, preOrderCallback , postOrderCallback); 167 WebInspector.TimelineModel.forAllRecords(this._records, preOrderCallback , postOrderCallback);
178 }, 168 },
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 return false; 217 return false;
228 } 218 }
229 return true; 219 return true;
230 }, 220 },
231 221
232 _filterChanged: function() 222 _filterChanged: function()
233 { 223 {
234 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordFi lterChanged); 224 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordFi lterChanged);
235 }, 225 },
236 226
237 /**
238 * @param {boolean} captureStacks
239 * @param {boolean} captureMemory
240 */
241 startRecording: function(captureStacks, captureMemory)
242 {
243 this._clientInitiatedRecording = true;
244 this.reset();
245 var maxStackFrames = captureStacks ? 30 : 0;
246 this._bufferEvents = WebInspector.experimentsSettings.timelineNoLiveUpda te.isEnabled();
247 var includeGPUEvents = WebInspector.experimentsSettings.gpuTimeline.isEn abled();
248 var liveEvents = [ WebInspector.TimelineModel.RecordType.BeginFrame,
249 WebInspector.TimelineModel.RecordType.DrawFrame,
250 WebInspector.TimelineModel.RecordType.RequestMainThre adFrame,
251 WebInspector.TimelineModel.RecordType.ActivateLayerTr ee ];
252 this._timelineManager.start(maxStackFrames, this._bufferEvents, liveEven ts.join(","), captureMemory, includeGPUEvents, this._fireRecordingStarted.bind(t his));
253 },
254
255 stopRecording: function()
256 {
257 if (!this._clientInitiatedRecording) {
258 this._timelineManager.start(undefined, undefined, undefined, undefin ed, undefined, stopTimeline.bind(this));
259 return;
260 }
261
262 /**
263 * Console started this one and we are just sniffing it. Initiate record ing so that we
264 * could stop it.
265 * @this {WebInspector.TimelineModel}
266 */
267 function stopTimeline()
268 {
269 this._timelineManager.stop(this._fireRecordingStopped.bind(this));
270 }
271
272 this._clientInitiatedRecording = false;
273 this._timelineManager.stop(this._fireRecordingStopped.bind(this));
274 },
275
276 willStartRecordingTraceEvents: function() 227 willStartRecordingTraceEvents: function()
277 { 228 {
278 this.reset(); 229 this.reset();
279 this._fireRecordingStarted(); 230 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStarted);
280 }, 231 },
281 232
282 /** 233 /**
283 * @param {!Array.<!WebInspector.TracingModel.Event>} mainThreadEvents 234 * @param {!Array.<!WebInspector.TracingModel.Event>} mainThreadEvents
284 */ 235 */
285 didStopRecordingTraceEvents: function(mainThreadEvents) 236 didStopRecordingTraceEvents: function(mainThreadEvents)
286 { 237 {
287 var recordStack = []; 238 var recordStack = [];
288 for (var i = 0, size = mainThreadEvents.length; i < size; ++i) { 239 for (var i = 0, size = mainThreadEvents.length; i < size; ++i) {
289 var event = mainThreadEvents[i]; 240 var event = mainThreadEvents[i];
290 while (recordStack.length) { 241 while (recordStack.length) {
291 var top = recordStack.peekLast(); 242 var top = recordStack.peekLast();
292 if (top._event.endTime >= event.startTime) 243 if (top._event.endTime >= event.startTime)
293 break; 244 break;
294 recordStack.pop(); 245 recordStack.pop();
295 } 246 }
296 var parentRecord = recordStack.peekLast() || null; 247 var parentRecord = recordStack.peekLast() || null;
297 var record = new WebInspector.TimelineModel.TraceEventRecord(this, e vent, parentRecord); 248 var record = new WebInspector.TimelineModel.TraceEventRecord(this, e vent, parentRecord);
298 if (WebInspector.TimelineUIUtils.isEventDivider(record)) 249 if (WebInspector.TimelineUIUtils.isEventDivider(record))
299 this._eventDividerRecords.push(record); 250 this._eventDividerRecords.push(record);
300 if (!recordStack.length) 251 if (!recordStack.length)
301 this._addTopLevelRecord(record); 252 this._addTopLevelRecord(record);
302 if (event.endTime) 253 if (event.endTime)
303 recordStack.push(record); 254 recordStack.push(record);
304 } 255 }
305 this._fireRecordingStopped(null, null); 256 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStopped);
306 }, 257 },
307 258
308 /** 259 /**
309 * @param {!WebInspector.TimelineModel.TraceEventRecord} record 260 * @param {!WebInspector.TimelineModel.TraceEventRecord} record
310 */ 261 */
311 _addTopLevelRecord: function(record) 262 _addTopLevelRecord: function(record)
312 { 263 {
313 this._updateBoundaries(record); 264 this._updateBoundaries(record);
314 this._records.push(record); 265 this._records.push(record);
315 if (record.type() === WebInspector.TimelineModel.RecordType.Program) 266 if (record.type() === WebInspector.TimelineModel.RecordType.Program)
316 this._mainThreadTasks.push(record); 267 this._mainThreadTasks.push(record);
317 if (record.type() === WebInspector.TimelineModel.RecordType.GPUTask) 268 if (record.type() === WebInspector.TimelineModel.RecordType.GPUTask)
318 this._gpuThreadTasks.push(record); 269 this._gpuThreadTasks.push(record);
319 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAd ded, record); 270 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAd ded, record);
320 }, 271 },
321 272
322 /** 273 /**
323 * @return {!Array.<!WebInspector.TimelineModel.Record>} 274 * @return {!Array.<!WebInspector.TimelineModel.Record>}
324 */ 275 */
325 records: function() 276 records: function()
326 { 277 {
327 return this._records; 278 return this._records;
328 }, 279 },
329 280
330 /** 281 /**
331 * @param {!WebInspector.Event} event
332 */
333 _onRecordAdded: function(event)
334 {
335 if (this._collectionEnabled)
336 this._addRecord(/** @type {!TimelineAgent.TimelineEvent} */(event.da ta));
337 },
338
339 /**
340 * @param {!WebInspector.Event} event
341 */
342 _onStarted: function(event)
343 {
344 if (event.data) {
345 // Started from console.
346 this._fireRecordingStarted();
347 }
348 },
349
350 /**
351 * @param {!WebInspector.Event} event
352 */
353 _onStopped: function(event)
354 {
355 if (event.data) {
356 // Stopped from console.
357 this._fireRecordingStopped(null, null);
358 }
359 },
360
361 /**
362 * @param {!WebInspector.Event} event
363 */
364 _onProgress: function(event)
365 {
366 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gProgress, event.data);
367 },
368
369 _fireRecordingStarted: function()
370 {
371 this._collectionEnabled = true;
372 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStarted);
373 },
374
375 /**
376 * @param {?Protocol.Error} error
377 * @param {?ProfilerAgent.CPUProfile} cpuProfile
378 */
379 _fireRecordingStopped: function(error, cpuProfile)
380 {
381 this._bufferEvents = false;
382 this._collectionEnabled = false;
383 if (cpuProfile)
384 WebInspector.TimelineJSProfileProcessor.mergeJSProfileIntoTimeline(t his, cpuProfile);
385 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.Recordin gStopped);
386 },
387
388 /**
389 * @return {boolean} 282 * @return {boolean}
390 */ 283 */
391 bufferEvents: function() 284 bufferEvents: function()
392 { 285 {
393 return this._bufferEvents; 286 return false;
394 }, 287 },
395 288
396 /** 289 /**
397 * @param {!TimelineAgent.TimelineEvent} payload
398 */
399 _addRecord: function(payload)
400 {
401 this._internStrings(payload);
402 this._payloads.push(payload);
403
404 var record = this._innerAddRecord(payload, null);
405 this._updateBoundaries(record);
406 this._records.push(record);
407 if (record.type() === WebInspector.TimelineModel.RecordType.Program)
408 this._mainThreadTasks.push(record);
409 if (record.type() === WebInspector.TimelineModel.RecordType.GPUTask)
410 this._gpuThreadTasks.push(record);
411
412 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAd ded, record);
413 },
414
415 /**
416 * @param {!TimelineAgent.TimelineEvent} payload
417 * @param {?WebInspector.TimelineModel.Record} parentRecord
418 * @return {!WebInspector.TimelineModel.Record}
419 * @this {!WebInspector.TimelineModel}
420 */
421 _innerAddRecord: function(payload, parentRecord)
422 {
423 var record = new WebInspector.TimelineModel.RecordImpl(this, payload, pa rentRecord);
424 if (WebInspector.TimelineUIUtils.isEventDivider(record))
425 this._eventDividerRecords.push(record);
426
427 for (var i = 0; payload.children && i < payload.children.length; ++i)
428 this._innerAddRecord.call(this, payload.children[i], record);
429
430 record._calculateAggregatedStats();
431 if (parentRecord)
432 parentRecord._selfTime -= record.endTime() - record.startTime();
433 return record;
434 },
435
436 /**
437 * @param {!Blob} file 290 * @param {!Blob} file
438 * @param {!WebInspector.Progress} progress 291 * @param {!WebInspector.Progress} progress
439 */ 292 */
440 loadFromFile: function(file, progress) 293 loadFromFile: function(file, progress)
441 { 294 {
442 var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this, progress); 295 throw new Error("Not implemented");
443 var fileReader = this._createFileReader(file, delegate);
444 var loader = new WebInspector.TimelineModelLoader(this, fileReader, prog ress);
445 fileReader.start(loader);
446 }, 296 },
447 297
448 /** 298 /**
449 * @param {string} url 299 * @param {string} url
450 * @param {!WebInspector.Progress} progress 300 * @param {!WebInspector.Progress} progress
451 */ 301 */
452 loadFromURL: function(url, progress) 302 loadFromURL: function(url, progress)
453 { 303 {
454 var delegate = new WebInspector.TimelineModelLoadFromFileDelegate(this, progress); 304 throw new Error("Not implemented");
455 var urlReader = new WebInspector.ChunkedXHRReader(url, delegate);
456 var loader = new WebInspector.TimelineModelLoader(this, urlReader, progr ess);
457 urlReader.start(loader);
458 },
459
460 _createFileReader: function(file, delegate)
461 {
462 return new WebInspector.ChunkedFileReader(file, WebInspector.TimelineMod el.TransferChunkLengthBytes, delegate);
463 },
464
465 _createFileWriter: function()
466 {
467 return new WebInspector.FileOutputStream();
468 }, 305 },
469 306
470 saveToFile: function() 307 saveToFile: function()
471 { 308 {
472 var now = new Date(); 309 throw new Error("Not implemented");
473 var fileName = "TimelineRawData-" + now.toISO8601Compact() + ".json";
474 var stream = this._createFileWriter();
475
476 /**
477 * @param {boolean} accepted
478 * @this {WebInspector.TimelineModel}
479 */
480 function callback(accepted)
481 {
482 if (!accepted)
483 return;
484 var saver = new WebInspector.TimelineSaver(stream);
485 saver.save(this._payloads, window.navigator.appVersion);
486 }
487 stream.open(fileName, callback.bind(this));
488 }, 310 },
489 311
490 reset: function() 312 reset: function()
491 { 313 {
492 this._loadedFromFile = false; 314 this._loadedFromFile = false;
493 this._records = []; 315 this._records = [];
494 this._payloads = [];
495 this._stringPool = {};
496 this._minimumRecordTime = -1; 316 this._minimumRecordTime = -1;
497 this._maximumRecordTime = -1; 317 this._maximumRecordTime = -1;
498 this._bindings._reset();
499 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */ 318 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */
500 this._mainThreadTasks = []; 319 this._mainThreadTasks = [];
501 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */ 320 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */
502 this._gpuThreadTasks = []; 321 this._gpuThreadTasks = [];
503 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */ 322 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */
504 this._eventDividerRecords = []; 323 this._eventDividerRecords = [];
505 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordsC leared); 324 this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordsC leared);
506 }, 325 },
507 326
508 /** 327 /**
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 }, 371 },
553 372
554 /** 373 /**
555 * @return {!Array.<!WebInspector.TimelineModel.Record>} 374 * @return {!Array.<!WebInspector.TimelineModel.Record>}
556 */ 375 */
557 eventDividerRecords: function() 376 eventDividerRecords: function()
558 { 377 {
559 return this._eventDividerRecords; 378 return this._eventDividerRecords;
560 }, 379 },
561 380
562 /**
563 * @param {!TimelineAgent.TimelineEvent} record
564 */
565 _internStrings: function(record)
566 {
567 for (var name in record) {
568 var value = record[name];
569 if (typeof value !== "string")
570 continue;
571
572 var interned = this._stringPool[value];
573 if (typeof interned === "string")
574 record[name] = interned;
575 else
576 this._stringPool[value] = value;
577 }
578
579 var children = record.children;
580 for (var i = 0; children && i < children.length; ++i)
581 this._internStrings(children[i]);
582 },
583
584 __proto__: WebInspector.Object.prototype 381 __proto__: WebInspector.Object.prototype
585 } 382 }
586 383
587
588 /**
589 * @constructor
590 */
591 WebInspector.TimelineModel.InterRecordBindings = function() {
592 this._reset();
593 }
594
595 WebInspector.TimelineModel.InterRecordBindings.prototype = {
596 _reset: function()
597 {
598 this._sendRequestRecords = {};
599 this._timerRecords = {};
600 this._requestAnimationFrameRecords = {};
601 this._layoutInvalidate = {};
602 this._lastScheduleStyleRecalculation = {};
603 this._webSocketCreateRecords = {};
604 }
605 }
606
607 /** 384 /**
608 * @interface 385 * @interface
609 */ 386 */
610 WebInspector.TimelineModel.Record = function() 387 WebInspector.TimelineModel.Record = function()
611 { 388 {
612 } 389 }
613 390
614 WebInspector.TimelineModel.Record.prototype = { 391 WebInspector.TimelineModel.Record.prototype = {
615 /** 392 /**
616 * @return {?Array.<!ConsoleAgent.CallFrame>} 393 * @return {?Array.<!ConsoleAgent.CallFrame>}
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after
921 if (data) { 698 if (data) {
922 for (var key in data) 699 for (var key in data)
923 tokens.push(data[key]); 700 tokens.push(data[key]);
924 } 701 }
925 return regExp.test(tokens.join("|")); 702 return regExp.test(tokens.join("|"));
926 } 703 }
927 } 704 }
928 705
929 /** 706 /**
930 * @constructor 707 * @constructor
931 * @implements {WebInspector.TimelineModel.Record}
932 * @param {!WebInspector.TimelineModel} model
933 * @param {!TimelineAgent.TimelineEvent} timelineEvent
934 * @param {?WebInspector.TimelineModel.Record} parentRecord
935 */
936 WebInspector.TimelineModel.RecordImpl = function(model, timelineEvent, parentRec ord)
937 {
938 this._model = model;
939 var bindings = this._model._bindings;
940 this._aggregatedStats = {};
941 this._record = timelineEvent;
942 this._children = [];
943 if (parentRecord) {
944 this.parent = parentRecord;
945 parentRecord.children().push(this);
946 }
947
948 this._selfTime = this.endTime() - this.startTime();
949
950 var recordTypes = WebInspector.TimelineModel.RecordType;
951 switch (timelineEvent.type) {
952 case recordTypes.ResourceSendRequest:
953 // Make resource receive record last since request was sent; make finish record last since response received.
954 bindings._sendRequestRecords[timelineEvent.data["requestId"]] = this;
955 break;
956
957 case recordTypes.ResourceReceiveResponse:
958 case recordTypes.ResourceReceivedData:
959 case recordTypes.ResourceFinish:
960 this._initiator = bindings._sendRequestRecords[timelineEvent.data["reque stId"]];
961 break;
962
963 case recordTypes.TimerInstall:
964 bindings._timerRecords[timelineEvent.data["timerId"]] = this;
965 break;
966
967 case recordTypes.TimerFire:
968 this._initiator = bindings._timerRecords[timelineEvent.data["timerId"]];
969 break;
970
971 case recordTypes.RequestAnimationFrame:
972 bindings._requestAnimationFrameRecords[timelineEvent.data["id"]] = this;
973 break;
974
975 case recordTypes.FireAnimationFrame:
976 this._initiator = bindings._requestAnimationFrameRecords[timelineEvent.d ata["id"]];
977 break;
978
979 case recordTypes.ScheduleStyleRecalculation:
980 bindings._lastScheduleStyleRecalculation[this.frameId()] = this;
981 break;
982
983 case recordTypes.RecalculateStyles:
984 this._initiator = bindings._lastScheduleStyleRecalculation[this.frameId( )];
985 break;
986
987 case recordTypes.InvalidateLayout:
988 // Consider style recalculation as a reason for layout invalidation,
989 // but only if we had no earlier layout invalidation records.
990 var layoutInitator = this;
991 if (!bindings._layoutInvalidate[this.frameId()] && parentRecord.type() = == recordTypes.RecalculateStyles)
992 layoutInitator = parentRecord._initiator;
993 bindings._layoutInvalidate[this.frameId()] = layoutInitator;
994 break;
995
996 case recordTypes.Layout:
997 this._initiator = bindings._layoutInvalidate[this.frameId()];
998 bindings._layoutInvalidate[this.frameId()] = null;
999 if (this.stackTrace())
1000 this.addWarning(WebInspector.UIString("Forced synchronous layout is a possible performance bottleneck."));
1001 break;
1002
1003 case recordTypes.WebSocketCreate:
1004 bindings._webSocketCreateRecords[timelineEvent.data["identifier"]] = thi s;
1005 break;
1006
1007 case recordTypes.WebSocketSendHandshakeRequest:
1008 case recordTypes.WebSocketReceiveHandshakeResponse:
1009 case recordTypes.WebSocketDestroy:
1010 this._initiator = bindings._webSocketCreateRecords[timelineEvent.data["i dentifier"]];
1011 break;
1012 }
1013 }
1014
1015 WebInspector.TimelineModel.RecordImpl.prototype = {
1016 /**
1017 * @return {?Array.<!ConsoleAgent.CallFrame>}
1018 */
1019 callSiteStackTrace: function()
1020 {
1021 return this._initiator ? this._initiator.stackTrace() : null;
1022 },
1023
1024 /**
1025 * @return {?WebInspector.TimelineModel.Record}
1026 */
1027 initiator: function()
1028 {
1029 return this._initiator;
1030 },
1031
1032 /**
1033 * @return {!WebInspector.Target}
1034 */
1035 target: function()
1036 {
1037 return this._model.target();
1038 },
1039
1040 /**
1041 * @return {number}
1042 */
1043 selfTime: function()
1044 {
1045 return this._selfTime;
1046 },
1047
1048 /**
1049 * @return {!Array.<!WebInspector.TimelineModel.Record>}
1050 */
1051 children: function()
1052 {
1053 return this._children;
1054 },
1055
1056 /**
1057 * @return {!WebInspector.TimelineCategory}
1058 */
1059 category: function()
1060 {
1061 return WebInspector.TimelineUIUtils.categoryForRecord(this);
1062 },
1063
1064 /**
1065 * @return {string}
1066 */
1067 title: function()
1068 {
1069 return WebInspector.TimelineUIUtils.recordTitle(this, this._model);
1070 },
1071
1072 /**
1073 * @return {number}
1074 */
1075 startTime: function()
1076 {
1077 return this._record.startTime;
1078 },
1079
1080 /**
1081 * @return {string|undefined}
1082 */
1083 thread: function()
1084 {
1085 return this._record.thread;
1086 },
1087
1088 /**
1089 * @return {number}
1090 */
1091 endTime: function()
1092 {
1093 return this._endTime || this._record.endTime || this._record.startTime;
1094 },
1095
1096 /**
1097 * @param {number} endTime
1098 */
1099 setEndTime: function(endTime)
1100 {
1101 this._endTime = endTime;
1102 },
1103
1104 /**
1105 * @return {!Object}
1106 */
1107 data: function()
1108 {
1109 return this._record.data;
1110 },
1111
1112 /**
1113 * @return {string}
1114 */
1115 type: function()
1116 {
1117 return this._record.type;
1118 },
1119
1120 /**
1121 * @return {string}
1122 */
1123 frameId: function()
1124 {
1125 return this._record.frameId || "";
1126 },
1127
1128 /**
1129 * @return {?Array.<!ConsoleAgent.CallFrame>}
1130 */
1131 stackTrace: function()
1132 {
1133 if (this._record.stackTrace && this._record.stackTrace.length)
1134 return this._record.stackTrace;
1135 return null;
1136 },
1137
1138 /**
1139 * @param {string} key
1140 * @return {?Object}
1141 */
1142 getUserObject: function(key)
1143 {
1144 if (!this._userObjects)
1145 return null;
1146 return this._userObjects.get(key);
1147 },
1148
1149 /**
1150 * @param {string} key
1151 * @param {?Object|undefined} value
1152 */
1153 setUserObject: function(key, value)
1154 {
1155 if (!this._userObjects)
1156 this._userObjects = new StringMap();
1157 this._userObjects.put(key, value);
1158 },
1159
1160 _calculateAggregatedStats: function()
1161 {
1162 this._aggregatedStats = {};
1163
1164 for (var index = this._children.length; index; --index) {
1165 var child = this._children[index - 1];
1166 for (var category in child._aggregatedStats)
1167 this._aggregatedStats[category] = (this._aggregatedStats[categor y] || 0) + child._aggregatedStats[category];
1168 }
1169 this._aggregatedStats[this.category().name] = (this._aggregatedStats[thi s.category().name] || 0) + this._selfTime;
1170 },
1171
1172 /**
1173 * @return {!Object.<string, number>}
1174 */
1175 aggregatedStats: function()
1176 {
1177 return this._aggregatedStats;
1178 },
1179
1180 /**
1181 * @param {string} message
1182 */
1183 addWarning: function(message)
1184 {
1185 if (!this._warnings)
1186 this._warnings = [];
1187 this._warnings.push(message);
1188 },
1189
1190 /**
1191 * @return {?Array.<string>}
1192 */
1193 warnings: function()
1194 {
1195 return this._warnings;
1196 },
1197
1198 /**
1199 * @param {!RegExp} regExp
1200 * @return {boolean}
1201 */
1202 testContentMatching: function(regExp)
1203 {
1204 var tokens = [this.title()];
1205 for (var key in this._record.data)
1206 tokens.push(this._record.data[key])
1207 return regExp.test(tokens.join("|"));
1208 }
1209 }
1210
1211 /**
1212 * @constructor
1213 */ 708 */
1214 WebInspector.TimelineModel.Filter = function() 709 WebInspector.TimelineModel.Filter = function()
1215 { 710 {
1216 /** @type {!WebInspector.TimelineModel} */ 711 /** @type {!WebInspector.TimelineModel} */
1217 this._model; 712 this._model;
1218 } 713 }
1219 714
1220 WebInspector.TimelineModel.Filter.prototype = { 715 WebInspector.TimelineModel.Filter.prototype = {
1221 /** 716 /**
1222 * @param {!WebInspector.TimelineModel.Record} record 717 * @param {!WebInspector.TimelineModel.Record} record
1223 * @return {boolean} 718 * @return {boolean}
1224 */ 719 */
1225 accept: function(record) 720 accept: function(record)
1226 { 721 {
1227 return true; 722 return true;
1228 }, 723 },
1229 724
1230 notifyFilterChanged: function() 725 notifyFilterChanged: function()
1231 { 726 {
1232 this._model._filterChanged(); 727 this._model._filterChanged();
1233 } 728 }
1234 } 729 }
1235 730
1236 /** 731 /**
1237 * @constructor 732 * @constructor
1238 * @implements {WebInspector.OutputStream}
1239 * @param {!WebInspector.TimelineModel} model
1240 * @param {!{cancel: function()}} reader
1241 * @param {!WebInspector.Progress} progress
1242 */
1243 WebInspector.TimelineModelLoader = function(model, reader, progress)
1244 {
1245 this._model = model;
1246 this._reader = reader;
1247 this._progress = progress;
1248 this._buffer = "";
1249 this._firstChunk = true;
1250 }
1251
1252 WebInspector.TimelineModelLoader.prototype = {
1253 /**
1254 * @param {string} chunk
1255 */
1256 write: function(chunk)
1257 {
1258 var data = this._buffer + chunk;
1259 var lastIndex = 0;
1260 var index;
1261 do {
1262 index = lastIndex;
1263 lastIndex = WebInspector.TextUtils.findBalancedCurlyBrackets(data, i ndex);
1264 } while (lastIndex !== -1)
1265
1266 var json = data.slice(0, index) + "]";
1267 this._buffer = data.slice(index);
1268
1269 if (!index)
1270 return;
1271
1272 // Prepending "0" to turn string into valid JSON.
1273 if (!this._firstChunk)
1274 json = "[0" + json;
1275
1276 var items;
1277 try {
1278 items = /** @type {!Array.<!TimelineAgent.TimelineEvent>} */ (JSON.p arse(json));
1279 } catch (e) {
1280 WebInspector.messageSink.addErrorMessage("Malformed timeline data.", true);
1281 this._model.reset();
1282 this._reader.cancel();
1283 this._progress.done();
1284 return;
1285 }
1286
1287 if (this._firstChunk) {
1288 this._version = items[0];
1289 this._firstChunk = false;
1290 this._model.reset();
1291 }
1292
1293 // Skip 0-th element - it is either version or 0.
1294 for (var i = 1, size = items.length; i < size; ++i)
1295 this._model._addRecord(items[i]);
1296 },
1297
1298 close: function()
1299 {
1300 this._model._loadedFromFile = true;
1301 }
1302 }
1303
1304 /**
1305 * @constructor
1306 * @implements {WebInspector.OutputStreamDelegate}
1307 * @param {!WebInspector.TimelineModel} model
1308 * @param {!WebInspector.Progress} progress
1309 */
1310 WebInspector.TimelineModelLoadFromFileDelegate = function(model, progress)
1311 {
1312 this._model = model;
1313 this._progress = progress;
1314 }
1315
1316 WebInspector.TimelineModelLoadFromFileDelegate.prototype = {
1317 onTransferStarted: function()
1318 {
1319 this._progress.setTitle(WebInspector.UIString("Loading\u2026"));
1320 },
1321
1322 /**
1323 * @param {!WebInspector.ChunkedReader} reader
1324 */
1325 onChunkTransferred: function(reader)
1326 {
1327 if (this._progress.isCanceled()) {
1328 reader.cancel();
1329 this._progress.done();
1330 this._model.reset();
1331 return;
1332 }
1333
1334 var totalSize = reader.fileSize();
1335 if (totalSize) {
1336 this._progress.setTotalWork(totalSize);
1337 this._progress.setWorked(reader.loadedSize());
1338 }
1339 },
1340
1341 onTransferFinished: function()
1342 {
1343 this._progress.done();
1344 },
1345
1346 /**
1347 * @param {!WebInspector.ChunkedReader} reader
1348 * @param {!Event} event
1349 */
1350 onError: function(reader, event)
1351 {
1352 this._progress.done();
1353 this._model.reset();
1354 switch (event.target.error.code) {
1355 case FileError.NOT_FOUND_ERR:
1356 WebInspector.messageSink.addErrorMessage(WebInspector.UIString("File \"%s\" not found.", reader.fileName()), true);
1357 break;
1358 case FileError.NOT_READABLE_ERR:
1359 WebInspector.messageSink.addErrorMessage(WebInspector.UIString("File \"%s\" is not readable", reader.fileName()), true);
1360 break;
1361 case FileError.ABORT_ERR:
1362 break;
1363 default:
1364 WebInspector.messageSink.addErrorMessage(WebInspector.UIString("An e rror occurred while reading the file \"%s\"", reader.fileName()), true);
1365 }
1366 }
1367 }
1368
1369 /**
1370 * @constructor
1371 * @param {!WebInspector.OutputStream} stream
1372 */
1373 WebInspector.TimelineSaver = function(stream)
1374 {
1375 this._stream = stream;
1376 }
1377
1378 WebInspector.TimelineSaver.prototype = {
1379 /**
1380 * @param {!Array.<*>} payloads
1381 * @param {string} version
1382 */
1383 save: function(payloads, version)
1384 {
1385 this._payloads = payloads;
1386 this._recordIndex = 0;
1387 this._prologue = "[" + JSON.stringify(version);
1388
1389 this._writeNextChunk(this._stream);
1390 },
1391
1392 _writeNextChunk: function(stream)
1393 {
1394 const separator = ",\n";
1395 var data = [];
1396 var length = 0;
1397
1398 if (this._prologue) {
1399 data.push(this._prologue);
1400 length += this._prologue.length;
1401 delete this._prologue;
1402 } else {
1403 if (this._recordIndex === this._payloads.length) {
1404 stream.close();
1405 return;
1406 }
1407 data.push("");
1408 }
1409 while (this._recordIndex < this._payloads.length) {
1410 var item = JSON.stringify(this._payloads[this._recordIndex]);
1411 var itemLength = item.length + separator.length;
1412 if (length + itemLength > WebInspector.TimelineModel.TransferChunkLe ngthBytes)
1413 break;
1414 length += itemLength;
1415 data.push(item);
1416 ++this._recordIndex;
1417 }
1418 if (this._recordIndex === this._payloads.length)
1419 data.push(data.pop() + "]");
1420 stream.write(data.join(separator), this._writeNextChunk.bind(this));
1421 }
1422 }
1423
1424 /**
1425 * @constructor
1426 */ 733 */
1427 WebInspector.TimelineMergingRecordBuffer = function() 734 WebInspector.TimelineMergingRecordBuffer = function()
1428 { 735 {
1429 this._backgroundRecordsBuffer = []; 736 this._backgroundRecordsBuffer = [];
1430 } 737 }
1431 738
1432 /** 739 /**
1433 * @constructor 740 * @constructor
1434 */ 741 */
1435 WebInspector.TimelineMergingRecordBuffer.prototype = { 742 WebInspector.TimelineMergingRecordBuffer.prototype = {
(...skipping 15 matching lines...) Expand all
1451 function recordTimestampComparator(a, b) 758 function recordTimestampComparator(a, b)
1452 { 759 {
1453 // Never return 0, as the merge function will squash identical entri es. 760 // Never return 0, as the merge function will squash identical entri es.
1454 return a.startTime() < b.startTime() ? -1 : 1; 761 return a.startTime() < b.startTime() ? -1 : 1;
1455 } 762 }
1456 var result = this._backgroundRecordsBuffer.mergeOrdered(records, recordT imestampComparator); 763 var result = this._backgroundRecordsBuffer.mergeOrdered(records, recordT imestampComparator);
1457 this._backgroundRecordsBuffer = []; 764 this._backgroundRecordsBuffer = [];
1458 return result; 765 return result;
1459 } 766 }
1460 } 767 }
OLDNEW
« no previous file with comments | « Source/devtools/devtools.gypi ('k') | Source/devtools/front_end/timeline/TimelineModelImpl.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698