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

Side by Side Diff: Source/devtools/front_end/TimelinePresentationModel.js

Issue 180273023: DevTools: encapsulate presentation model in timeline view. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * Copyright (C) 2012 Intel Inc. All rights reserved. 3 * Copyright (C) 2012 Intel Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are 6 * modification, are permitted provided that the following conditions are
7 * met: 7 * met:
8 * 8 *
9 * * Redistributions of source code must retain the above copyright 9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 15 matching lines...) Expand all
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32 /** 32 /**
33 * @constructor 33 * @constructor
34 * @extends {WebInspector.Object} 34 * @extends {WebInspector.Object}
35 * @param {!WebInspector.TimelineModel} model 35 * @param {!WebInspector.TimelineModel} model
36 * @param {!WebInspector.TimelineModeViewDelegate} delegate
36 */ 37 */
37 WebInspector.TimelinePresentationModel = function(model) 38 WebInspector.TimelinePresentationModel = function(model, delegate)
38 { 39 {
39 this._model = model; 40 this._model = model;
41 this._delegate = delegate;
40 this._filters = []; 42 this._filters = [];
41 /** 43 /**
42 * @type {!Map.<!WebInspector.TimelineModel.Record, !WebInspector.TimelinePr esentationModel.Record>} 44 * @type {!Map.<!WebInspector.TimelineModel.Record, !WebInspector.TimelinePr esentationModel.Record>}
43 */ 45 */
44 this._recordToPresentationRecord = new Map(); 46 this._recordToPresentationRecord = new Map();
45 this.reset(); 47 this.reset();
46 } 48 }
47 49
48 WebInspector.TimelinePresentationModel._hiddenRecords = { };
49 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.MarkDOMContent] = 1;
50 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.MarkLoad] = 1;
51 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.MarkFirstPaint] = 1;
52 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.GPUTask] = 1;
53 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.ScheduleStyleRecalculation] = 1;
54 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.InvalidateLayout] = 1;
55 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.RequestMainThreadFrame] = 1;
56 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.ActivateLayerTree] = 1;
57 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.DrawFrame] = 1;
58 WebInspector.TimelinePresentationModel._hiddenRecords[WebInspector.TimelineModel .RecordType.BeginFrame] = 1;
59
60 WebInspector.TimelinePresentationModel._coalescingRecords = { }; 50 WebInspector.TimelinePresentationModel._coalescingRecords = { };
61 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.Layout] = 1; 51 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.Layout] = 1;
62 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.Paint] = 1; 52 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.Paint] = 1;
63 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.Rasterize] = 1; 53 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.Rasterize] = 1;
64 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.DecodeImage] = 1; 54 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.DecodeImage] = 1;
65 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.ResizeImage] = 1; 55 WebInspector.TimelinePresentationModel._coalescingRecords[WebInspector.TimelineM odel.RecordType.ResizeImage] = 1;
66 56
67 WebInspector.TimelinePresentationModel.prototype = { 57 WebInspector.TimelinePresentationModel.prototype = {
68 /** 58 /**
69 * @param {?WebInspector.TimelineModel.Record} record 59 * @param {?WebInspector.TimelineModel.Record} record
70 * @return {?WebInspector.TimelinePresentationModel.Record} 60 * @return {?WebInspector.TimelinePresentationModel.Record}
71 */ 61 */
72 toPresentationRecord: function(record) 62 toPresentationRecord: function(record)
73 { 63 {
74 return record ? this._recordToPresentationRecord.get(record) || null : n ull; 64 return record ? this._recordToPresentationRecord.get(record) || null : n ull;
75 }, 65 },
76 66
77 /** 67 /**
78 * @param {!WebInspector.TimelinePresentationModel.Filter} filter
79 */
80 addFilter: function(filter)
81 {
82 this._filters.push(filter);
83 },
84
85 /**
86 * @param {?WebInspector.TimelinePresentationModel.Filter} filter
87 */
88 setSearchFilter: function(filter)
89 {
90 if (!filter) {
91 var allRecords = this._recordToPresentationRecord.values();
92 for (var i = 0; i < allRecords.length; ++i)
93 delete allRecords[i].clicked;
94 }
95 this._searchFilter = filter;
96 },
97
98 /**
99 * @return {!WebInspector.TimelinePresentationModel.Record} 68 * @return {!WebInspector.TimelinePresentationModel.Record}
100 */ 69 */
101 rootRecord: function() 70 rootRecord: function()
102 { 71 {
103 return this._rootRecord; 72 return this._rootRecord;
104 }, 73 },
105 74
106 reset: function() 75 reset: function()
107 { 76 {
108 this._recordToPresentationRecord.clear(); 77 this._recordToPresentationRecord.clear();
109 var rootPayload = { type: WebInspector.TimelineModel.RecordType.Root }; 78 var rootPayload = { type: WebInspector.TimelineModel.RecordType.Root };
110 var rootRecord = new WebInspector.TimelineModel.Record(this._model, /** @type {!TimelineAgent.TimelineEvent} */ (rootPayload), null); 79 var rootRecord = new WebInspector.TimelineModel.Record(this._model, /** @type {!TimelineAgent.TimelineEvent} */ (rootPayload), null);
111 this._rootRecord = new WebInspector.TimelinePresentationModel.Record(roo tRecord, null); 80 this._rootRecord = new WebInspector.TimelinePresentationModel.Record(roo tRecord, null);
112 this._eventDividerRecords = [];
113 this._minimumRecordTime = -1;
114 /** @type {!Object.<string, !WebInspector.TimelinePresentationModel.Reco rd>} */ 81 /** @type {!Object.<string, !WebInspector.TimelinePresentationModel.Reco rd>} */
115 this._coalescingBuckets = {}; 82 this._coalescingBuckets = {};
116 this._mergingBuffer = new WebInspector.TimelineMergingRecordBuffer();
117
118 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */
119 this._mainThreadTasks = ([]);
120 /** @type {!Array.<!WebInspector.TimelineModel.Record>} */
121 this._gpuThreadTasks = ([]);
122 }, 83 },
123 84
124 /** 85 /**
125 * @return {number}
126 */
127 minimumRecordTime: function()
128 {
129 return this._minimumRecordTime;
130 },
131
132 /**
133 * @return {number}
134 */
135 maximumRecordTime: function()
136 {
137 return this._maximumRecordTime;
138 },
139
140 /**
141 * @return {!Array.<!WebInspector.TimelineModel.Record>}
142 */
143 mainThreadTasks: function()
144 {
145 return this._mainThreadTasks;
146 },
147
148 /**
149 * @return {!Array.<!WebInspector.TimelineModel.Record>}
150 */
151 gpuThreadTasks: function()
152 {
153 return this._gpuThreadTasks;
154 },
155
156 /**
157 * @param {!WebInspector.TimelineModel.Record} record 86 * @param {!WebInspector.TimelineModel.Record} record
158 */ 87 */
159 addRecord: function(record) 88 addRecord: function(record)
160 { 89 {
161 if (record.type === WebInspector.TimelineModel.RecordType.Program)
162 this._mainThreadTasks.push(record);
163 if (record.type === WebInspector.TimelineModel.RecordType.GPUTask)
164 this._gpuThreadTasks.push(record);
165
166 var startTime = record.startTime;
167 var endTime = record.endTime;
168 if (this._minimumRecordTime === -1 || startTime < this._minimumRecordTim e)
169 this._minimumRecordTime = startTime;
170 if (this._maximumRecordTime === -1 || endTime > this._maximumRecordTime)
171 this._maximumRecordTime = endTime;
172
173 var records; 90 var records;
174 if (record.type === WebInspector.TimelineModel.RecordType.Program) 91 if (record.type === WebInspector.TimelineModel.RecordType.Program)
175 records = record.children; 92 records = record.children;
176 else 93 else
177 records = [record]; 94 records = [record];
178 95
179 for (var i = 0; i < records.length; ++i) 96 for (var i = 0; i < records.length; ++i)
180 this._innerAddRecord(this._rootRecord, records[i]); 97 this._innerAddRecord(this._rootRecord, records[i]);
181 }, 98 },
182 99
183 /** 100 /**
184 * @param {!WebInspector.TimelinePresentationModel.Record} parentRecord 101 * @param {!WebInspector.TimelinePresentationModel.Record} parentRecord
185 * @param {!WebInspector.TimelineModel.Record} record 102 * @param {!WebInspector.TimelineModel.Record} record
186 */ 103 */
187 _innerAddRecord: function(parentRecord, record) 104 _innerAddRecord: function(parentRecord, record)
188 { 105 {
189 if (WebInspector.TimelineUIUtils.isEventDivider(record))
190 this._eventDividerRecords.push(record);
191
192 if (record.type in WebInspector.TimelinePresentationModel._hiddenRecords )
193 return null;
194
195 const recordTypes = WebInspector.TimelineModel.RecordType;
196
197 var origin = parentRecord;
198 var coalescingBucket; 106 var coalescingBucket;
199 107
200 // On main thread, only coalesce if the last event is of same type. 108 // On main thread, only coalesce if the last event is of same type.
201 if (parentRecord === this._rootRecord) 109 if (parentRecord === this._rootRecord)
202 coalescingBucket = record.thread ? record.type : "mainThread"; 110 coalescingBucket = record.thread ? record.type : "mainThread";
203 var coalescedRecord = this._findCoalescedParent(record, parentRecord, co alescingBucket); 111 var coalescedRecord = this._findCoalescedParent(record, parentRecord, co alescingBucket);
204 if (coalescedRecord) 112 if (coalescedRecord)
205 parentRecord = coalescedRecord; 113 parentRecord = coalescedRecord;
206 114
207 var formattedRecord = new WebInspector.TimelinePresentationModel.Record( record, parentRecord); 115 var formattedRecord = new WebInspector.TimelinePresentationModel.Record( record, parentRecord);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 var parentRecord = presentationRecord._presentationParent.record(); 201 var parentRecord = presentationRecord._presentationParent.record();
294 WebInspector.TimelineUIUtils.aggregateTimeByCategory(parentRecord.aggreg atedStats, record.aggregatedStats); 202 WebInspector.TimelineUIUtils.aggregateTimeByCategory(parentRecord.aggreg atedStats, record.aggregatedStats);
295 if (parentRecord.startTime > record.startTime) 203 if (parentRecord.startTime > record.startTime)
296 parentRecord.startTime = record.startTime; 204 parentRecord.startTime = record.startTime;
297 if (parentRecord.endTime < record.endTime) { 205 if (parentRecord.endTime < record.endTime) {
298 parentRecord.endTime = record.endTime; 206 parentRecord.endTime = record.endTime;
299 parentRecord.lastChildEndTime = parentRecord.endTime; 207 parentRecord.lastChildEndTime = parentRecord.endTime;
300 } 208 }
301 }, 209 },
302 210
211 /**
212 * @param {?RegExp} textFilter
213 */
214 setTextFilter: function(textFilter)
215 {
216 if (this._textFilter === textFilter)
217 return;
218 this._textFilter = textFilter;
219 for (var i = 0; this._filteredRecords && i < this._filteredRecords.lengt h; ++i)
220 delete this._filteredRecords[i]._expandedOrCollapsedWhileFiltered;
221 },
222
303 invalidateFilteredRecords: function() 223 invalidateFilteredRecords: function()
304 { 224 {
305 delete this._filteredRecords; 225 delete this._filteredRecords;
306 }, 226 },
307 227
308 /** 228 /**
309 * @return {!Array.<!WebInspector.TimelinePresentationModel.Record>} 229 * @return {!Array.<!WebInspector.TimelinePresentationModel.Record>}
310 */ 230 */
311 filteredRecords: function() 231 filteredRecords: function()
312 { 232 {
313 if (this._filteredRecords) 233 if (this._filteredRecords)
314 return this._filteredRecords; 234 return this._filteredRecords;
315 235
316 var recordsInWindow = []; 236 var recordsInWindow = [];
317 var stack = [{children: this._rootRecord._presentationChildren, index: 0 , parentIsCollapsed: false, parentRecord: {}}]; 237
318 var revealedDepth = 0; 238 var stack = [{children: this._rootRecord._presentationChildren, index: 0, parentIsCollapsed: false, parentRecord: {}}];
239 var revealedDepth = 0;
319 240
320 function revealRecordsInStack() { 241 function revealRecordsInStack() {
321 for (var depth = revealedDepth + 1; depth < stack.length; ++depth) { 242 for (var depth = revealedDepth + 1; depth < stack.length; ++depth) {
322 if (stack[depth - 1].parentIsCollapsed) { 243 if (stack[depth - 1].parentIsCollapsed) {
323 stack[depth].parentRecord._presentationParent._expandable = true; 244 stack[depth].parentRecord._presentationParent._expandable = true;
324 return; 245 return;
325 } 246 }
326 stack[depth - 1].parentRecord._collapsed = false; 247 stack[depth - 1].parentRecord._collapsed = false;
327 recordsInWindow.push(stack[depth].parentRecord); 248 recordsInWindow.push(stack[depth].parentRecord);
328 stack[depth].windowLengthBeforeChildrenTraversal = recordsInWind ow.length; 249 stack[depth].windowLengthBeforeChildrenTraversal = recordsInWind ow.length;
329 stack[depth].parentIsRevealed = true; 250 stack[depth].parentIsRevealed = true;
330 revealedDepth = depth; 251 revealedDepth = depth;
331 } 252 }
332 } 253 }
333 254
334 while (stack.length) { 255 while (stack.length) {
335 var entry = stack[stack.length - 1]; 256 var entry = stack[stack.length - 1];
336 var records = entry.children; 257 var records = entry.children;
337 if (records && entry.index < records.length) { 258 if (records && entry.index < records.length) {
338 var record = records[entry.index]; 259 var record = records[entry.index];
339 ++entry.index; 260 ++entry.index;
340 261
341 if (this.isVisible(record.record())) { 262 if (this._model.isVisible(record.record())) {
342 record._presentationParent._expandable = true; 263 record._presentationParent._expandable = true;
343 if (this._searchFilter) 264 if (this._textFilter)
344 revealRecordsInStack(); 265 revealRecordsInStack();
345 if (!entry.parentIsCollapsed) { 266 if (!entry.parentIsCollapsed) {
346 recordsInWindow.push(record); 267 recordsInWindow.push(record);
347 revealedDepth = stack.length; 268 revealedDepth = stack.length;
348 entry.parentRecord._collapsed = false; 269 entry.parentRecord._collapsed = false;
349 } 270 }
350 } 271 }
351 272
352 record._expandable = false; 273 record._expandable = false;
353 274
354 stack.push({children: record._presentationChildren, 275 stack.push({children: record._presentationChildren,
355 index: 0, 276 index: 0,
356 parentIsCollapsed: (entry.parentIsCollapsed || (reco rd._collapsed && (!this._searchFilter || record.clicked))), 277 parentIsCollapsed: entry.parentIsCollapsed || (recor d._collapsed && (!this._textFilter || record._expandedOrCollapsedWhileFiltered)) ,
357 parentRecord: record, 278 parentRecord: record,
358 windowLengthBeforeChildrenTraversal: recordsInWindow .length}); 279 windowLengthBeforeChildrenTraversal: recordsInWindow .length});
359 } else { 280 } else {
360 stack.pop(); 281 stack.pop();
361 revealedDepth = Math.min(revealedDepth, stack.length - 1); 282 revealedDepth = Math.min(revealedDepth, stack.length - 1);
362 entry.parentRecord._visibleChildrenCount = recordsInWindow.lengt h - entry.windowLengthBeforeChildrenTraversal; 283 entry.parentRecord._visibleChildrenCount = recordsInWindow.lengt h - entry.windowLengthBeforeChildrenTraversal;
363 } 284 }
364 } 285 }
365 286
366 this._filteredRecords = recordsInWindow; 287 this._filteredRecords = recordsInWindow;
367 return recordsInWindow; 288 return recordsInWindow;
368 }, 289 },
369 290
370 /**
371 * @return {!Array.<!WebInspector.TimelineModel.Record>}
372 */
373 eventDividerRecords: function()
374 {
375 return this._eventDividerRecords;
376 },
377
378 /**
379 * @param {!WebInspector.TimelineModel.Record} record
380 * @return {boolean}
381 */
382 isVisible: function(record)
383 {
384 for (var i = 0; i < this._filters.length; ++i) {
385 if (!this._filters[i].accept(record))
386 return false;
387 }
388 return !this._searchFilter || this._searchFilter.accept(record);
389 },
390
391 __proto__: WebInspector.Object.prototype 291 __proto__: WebInspector.Object.prototype
392 } 292 }
393 293
394 /** 294 /**
395 * @constructor 295 * @constructor
396 * @param {!WebInspector.TimelineModel.Record} record 296 * @param {!WebInspector.TimelineModel.Record} record
397 * @param {?WebInspector.TimelinePresentationModel.Record} parentRecord 297 * @param {?WebInspector.TimelinePresentationModel.Record} parentRecord
398 */ 298 */
399 WebInspector.TimelinePresentationModel.Record = function(record, parentRecord) 299 WebInspector.TimelinePresentationModel.Record = function(record, parentRecord)
400 { 300 {
(...skipping 20 matching lines...) Expand all
421 WebInspector.TimelinePresentationModel.Record.prototype = { 321 WebInspector.TimelinePresentationModel.Record.prototype = {
422 /** 322 /**
423 * @return {!WebInspector.TimelineModel.Record} 323 * @return {!WebInspector.TimelineModel.Record}
424 */ 324 */
425 record: function() 325 record: function()
426 { 326 {
427 return this._record; 327 return this._record;
428 }, 328 },
429 329
430 /** 330 /**
431 * @return {boolean}
432 */
433 isRoot: function()
434 {
435 return this.type === WebInspector.TimelineModel.RecordType.Root;
436 },
437
438 /**
439 * @return {!Array.<!WebInspector.TimelinePresentationModel.Record>} 331 * @return {!Array.<!WebInspector.TimelinePresentationModel.Record>}
440 */ 332 */
441 presentationChildren: function() 333 presentationChildren: function()
442 { 334 {
443 return this._presentationChildren; 335 return this._presentationChildren;
444 }, 336 },
445 337
446 /** 338 /**
447 * @return {boolean} 339 * @return {boolean}
448 */ 340 */
(...skipping 17 matching lines...) Expand all
466 { 358 {
467 return this._collapsed; 359 return this._collapsed;
468 }, 360 },
469 361
470 /** 362 /**
471 * @param {boolean} collapsed 363 * @param {boolean} collapsed
472 */ 364 */
473 setCollapsed: function(collapsed) 365 setCollapsed: function(collapsed)
474 { 366 {
475 this._collapsed = collapsed; 367 this._collapsed = collapsed;
368 this._expandedOrCollapsedWhileFiltered = true;
476 }, 369 },
477 370
478 /** 371 /**
479 * @return {?WebInspector.TimelinePresentationModel.Record} 372 * @return {?WebInspector.TimelinePresentationModel.Record}
480 */ 373 */
481 presentationParent: function() 374 presentationParent: function()
482 { 375 {
483 return this._presentationParent || null; 376 return this._presentationParent || null;
484 }, 377 },
485 378
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
540 }, 433 },
541 434
542 /** 435 /**
543 * @param {!WebInspector.TimelineRecordGraphRow} graphRow 436 * @param {!WebInspector.TimelineRecordGraphRow} graphRow
544 */ 437 */
545 setGraphRow: function(graphRow) 438 setGraphRow: function(graphRow)
546 { 439 {
547 this._graphRow = graphRow; 440 this._graphRow = graphRow;
548 } 441 }
549 } 442 }
550
551 /**
552 * @interface
553 */
554 WebInspector.TimelinePresentationModel.Filter = function()
555 {
556 }
557
558 WebInspector.TimelinePresentationModel.Filter.prototype = {
559 /**
560 * @param {!WebInspector.TimelineModel.Record} record
561 * @return {boolean}
562 */
563 accept: function(record) { return false; }
564 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698