OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | |
5 /** | 4 /** |
6 * @constructor | 5 * @unrestricted |
7 */ | 6 */ |
8 WebInspector.TimelineIRModel = function() | 7 WebInspector.TimelineIRModel = class { |
9 { | 8 constructor() { |
10 this.reset(); | 9 this.reset(); |
| 10 } |
| 11 |
| 12 /** |
| 13 * @param {!WebInspector.TracingModel.Event} event |
| 14 * @return {!WebInspector.TimelineIRModel.Phases} |
| 15 */ |
| 16 static phaseForEvent(event) { |
| 17 return event[WebInspector.TimelineIRModel._eventIRPhase]; |
| 18 } |
| 19 |
| 20 /** |
| 21 * @param {?Array<!WebInspector.TracingModel.AsyncEvent>} inputLatencies |
| 22 * @param {?Array<!WebInspector.TracingModel.AsyncEvent>} animations |
| 23 */ |
| 24 populate(inputLatencies, animations) { |
| 25 var eventTypes = WebInspector.TimelineIRModel.InputEvents; |
| 26 var phases = WebInspector.TimelineIRModel.Phases; |
| 27 |
| 28 this.reset(); |
| 29 if (!inputLatencies) |
| 30 return; |
| 31 this._processInputLatencies(inputLatencies); |
| 32 if (animations) |
| 33 this._processAnimations(animations); |
| 34 var range = new WebInspector.SegmentedRange(); |
| 35 range.appendRange(this._drags); // Drags take lower precedence than animati
on, as we can't detect them reliably. |
| 36 range.appendRange(this._cssAnimations); |
| 37 range.appendRange(this._scrolls); |
| 38 range.appendRange(this._responses); |
| 39 this._segments = range.segments(); |
| 40 } |
| 41 |
| 42 /** |
| 43 * @param {!Array<!WebInspector.TracingModel.AsyncEvent>} events |
| 44 */ |
| 45 _processInputLatencies(events) { |
| 46 var eventTypes = WebInspector.TimelineIRModel.InputEvents; |
| 47 var phases = WebInspector.TimelineIRModel.Phases; |
| 48 var thresholdsMs = WebInspector.TimelineIRModel._mergeThresholdsMs; |
| 49 |
| 50 var scrollStart; |
| 51 var flingStart; |
| 52 var touchStart; |
| 53 var firstTouchMove; |
| 54 var mouseWheel; |
| 55 var mouseDown; |
| 56 var mouseMove; |
| 57 |
| 58 for (var i = 0; i < events.length; ++i) { |
| 59 var event = events[i]; |
| 60 if (i > 0 && events[i].startTime < events[i - 1].startTime) |
| 61 console.assert(false, 'Unordered input events'); |
| 62 var type = this._inputEventType(event.name); |
| 63 switch (type) { |
| 64 case eventTypes.ScrollBegin: |
| 65 this._scrolls.append(this._segmentForEvent(event, phases.Scroll)); |
| 66 scrollStart = event; |
| 67 break; |
| 68 |
| 69 case eventTypes.ScrollEnd: |
| 70 if (scrollStart) |
| 71 this._scrolls.append(this._segmentForEventRange(scrollStart, event,
phases.Scroll)); |
| 72 else |
| 73 this._scrolls.append(this._segmentForEvent(event, phases.Scroll)); |
| 74 scrollStart = null; |
| 75 break; |
| 76 |
| 77 case eventTypes.ScrollUpdate: |
| 78 touchStart = null; // Since we're scrolling now, disregard other touc
h gestures. |
| 79 this._scrolls.append(this._segmentForEvent(event, phases.Scroll)); |
| 80 break; |
| 81 |
| 82 case eventTypes.FlingStart: |
| 83 if (flingStart) { |
| 84 WebInspector.console.error( |
| 85 WebInspector.UIString('Two flings at the same time? %s vs %s', f
lingStart.startTime, event.startTime)); |
| 86 break; |
| 87 } |
| 88 flingStart = event; |
| 89 break; |
| 90 |
| 91 case eventTypes.FlingCancel: |
| 92 // FIXME: also process renderer fling events. |
| 93 if (!flingStart) |
| 94 break; |
| 95 this._scrolls.append(this._segmentForEventRange(flingStart, event, pha
ses.Fling)); |
| 96 flingStart = null; |
| 97 break; |
| 98 |
| 99 case eventTypes.ImplSideFling: |
| 100 this._scrolls.append(this._segmentForEvent(event, phases.Fling)); |
| 101 break; |
| 102 |
| 103 case eventTypes.ShowPress: |
| 104 case eventTypes.Tap: |
| 105 case eventTypes.KeyDown: |
| 106 case eventTypes.KeyDownRaw: |
| 107 case eventTypes.KeyUp: |
| 108 case eventTypes.Char: |
| 109 case eventTypes.Click: |
| 110 case eventTypes.ContextMenu: |
| 111 this._responses.append(this._segmentForEvent(event, phases.Response)); |
| 112 break; |
| 113 |
| 114 case eventTypes.TouchStart: |
| 115 // We do not produce any response segment for TouchStart -- there's ei
ther going to be one upon |
| 116 // TouchMove for drag, or one for GestureTap. |
| 117 if (touchStart) { |
| 118 WebInspector.console.error( |
| 119 WebInspector.UIString('Two touches at the same time? %s vs %s',
touchStart.startTime, event.startTime)); |
| 120 break; |
| 121 } |
| 122 touchStart = event; |
| 123 event.steps[0][WebInspector.TimelineIRModel._eventIRPhase] = phases.Re
sponse; |
| 124 firstTouchMove = null; |
| 125 break; |
| 126 |
| 127 case eventTypes.TouchCancel: |
| 128 touchStart = null; |
| 129 break; |
| 130 |
| 131 case eventTypes.TouchMove: |
| 132 if (firstTouchMove) { |
| 133 this._drags.append(this._segmentForEvent(event, phases.Drag)); |
| 134 } else if (touchStart) { |
| 135 firstTouchMove = event; |
| 136 this._responses.append(this._segmentForEventRange(touchStart, event,
phases.Response)); |
| 137 } |
| 138 break; |
| 139 |
| 140 case eventTypes.TouchEnd: |
| 141 touchStart = null; |
| 142 break; |
| 143 |
| 144 case eventTypes.MouseDown: |
| 145 mouseDown = event; |
| 146 mouseMove = null; |
| 147 break; |
| 148 |
| 149 case eventTypes.MouseMove: |
| 150 if (mouseDown && !mouseMove && mouseDown.startTime + thresholdsMs.mous
e > event.startTime) { |
| 151 this._responses.append(this._segmentForEvent(mouseDown, phases.Respo
nse)); |
| 152 this._responses.append(this._segmentForEvent(event, phases.Response)
); |
| 153 } else if (mouseDown) { |
| 154 this._drags.append(this._segmentForEvent(event, phases.Drag)); |
| 155 } |
| 156 mouseMove = event; |
| 157 break; |
| 158 |
| 159 case eventTypes.MouseUp: |
| 160 this._responses.append(this._segmentForEvent(event, phases.Response)); |
| 161 mouseDown = null; |
| 162 break; |
| 163 |
| 164 case eventTypes.MouseWheel: |
| 165 // Do not consider first MouseWheel as trace viewer's implementation d
oes -- in case of MouseWheel it's not really special. |
| 166 if (mouseWheel && canMerge(thresholdsMs.mouse, mouseWheel, event)) |
| 167 this._scrolls.append(this._segmentForEventRange(mouseWheel, event, p
hases.Scroll)); |
| 168 else |
| 169 this._scrolls.append(this._segmentForEvent(event, phases.Scroll)); |
| 170 mouseWheel = event; |
| 171 break; |
| 172 } |
| 173 } |
| 174 |
| 175 /** |
| 176 * @param {number} threshold |
| 177 * @param {!WebInspector.TracingModel.AsyncEvent} first |
| 178 * @param {!WebInspector.TracingModel.AsyncEvent} second |
| 179 * @return {boolean} |
| 180 */ |
| 181 function canMerge(threshold, first, second) { |
| 182 return first.endTime < second.startTime && second.startTime < first.endTim
e + threshold; |
| 183 } |
| 184 } |
| 185 |
| 186 /** |
| 187 * @param {!Array<!WebInspector.TracingModel.AsyncEvent>} events |
| 188 */ |
| 189 _processAnimations(events) { |
| 190 for (var i = 0; i < events.length; ++i) |
| 191 this._cssAnimations.append(this._segmentForEvent(events[i], WebInspector.T
imelineIRModel.Phases.Animation)); |
| 192 } |
| 193 |
| 194 /** |
| 195 * @param {!WebInspector.TracingModel.AsyncEvent} event |
| 196 * @param {!WebInspector.TimelineIRModel.Phases} phase |
| 197 * @return {!WebInspector.Segment} |
| 198 */ |
| 199 _segmentForEvent(event, phase) { |
| 200 this._setPhaseForEvent(event, phase); |
| 201 return new WebInspector.Segment(event.startTime, event.endTime, phase); |
| 202 } |
| 203 |
| 204 /** |
| 205 * @param {!WebInspector.TracingModel.AsyncEvent} startEvent |
| 206 * @param {!WebInspector.TracingModel.AsyncEvent} endEvent |
| 207 * @param {!WebInspector.TimelineIRModel.Phases} phase |
| 208 * @return {!WebInspector.Segment} |
| 209 */ |
| 210 _segmentForEventRange(startEvent, endEvent, phase) { |
| 211 this._setPhaseForEvent(startEvent, phase); |
| 212 this._setPhaseForEvent(endEvent, phase); |
| 213 return new WebInspector.Segment(startEvent.startTime, endEvent.endTime, phas
e); |
| 214 } |
| 215 |
| 216 /** |
| 217 * @param {!WebInspector.TracingModel.AsyncEvent} asyncEvent |
| 218 * @param {!WebInspector.TimelineIRModel.Phases} phase |
| 219 */ |
| 220 _setPhaseForEvent(asyncEvent, phase) { |
| 221 asyncEvent.steps[0][WebInspector.TimelineIRModel._eventIRPhase] = phase; |
| 222 } |
| 223 |
| 224 /** |
| 225 * @return {!Array<!WebInspector.Segment>} |
| 226 */ |
| 227 interactionRecords() { |
| 228 return this._segments; |
| 229 } |
| 230 |
| 231 reset() { |
| 232 var thresholdsMs = WebInspector.TimelineIRModel._mergeThresholdsMs; |
| 233 |
| 234 this._segments = []; |
| 235 this._drags = new WebInspector.SegmentedRange(merge.bind(null, thresholdsMs.
mouse)); |
| 236 this._cssAnimations = new WebInspector.SegmentedRange(merge.bind(null, thres
holdsMs.animation)); |
| 237 this._responses = new WebInspector.SegmentedRange(merge.bind(null, 0)); |
| 238 this._scrolls = new WebInspector.SegmentedRange(merge.bind(null, thresholdsM
s.animation)); |
| 239 |
| 240 /** |
| 241 * @param {number} threshold |
| 242 * @param {!WebInspector.Segment} first |
| 243 * @param {!WebInspector.Segment} second |
| 244 */ |
| 245 function merge(threshold, first, second) { |
| 246 return first.end + threshold >= second.begin && first.data === second.data
? first : null; |
| 247 } |
| 248 } |
| 249 |
| 250 /** |
| 251 * @param {string} eventName |
| 252 * @return {?WebInspector.TimelineIRModel.InputEvents} |
| 253 */ |
| 254 _inputEventType(eventName) { |
| 255 var prefix = 'InputLatency::'; |
| 256 if (!eventName.startsWith(prefix)) { |
| 257 if (eventName === WebInspector.TimelineIRModel.InputEvents.ImplSideFling) |
| 258 return /** @type {!WebInspector.TimelineIRModel.InputEvents} */ (eventNa
me); |
| 259 console.error('Unrecognized input latency event: ' + eventName); |
| 260 return null; |
| 261 } |
| 262 return /** @type {!WebInspector.TimelineIRModel.InputEvents} */ (eventName.s
ubstr(prefix.length)); |
| 263 } |
11 }; | 264 }; |
12 | 265 |
13 /** | 266 /** |
14 * @enum {string} | 267 * @enum {string} |
15 */ | 268 */ |
16 WebInspector.TimelineIRModel.Phases = { | 269 WebInspector.TimelineIRModel.Phases = { |
17 Idle: "Idle", | 270 Idle: 'Idle', |
18 Response: "Response", | 271 Response: 'Response', |
19 Scroll: "Scroll", | 272 Scroll: 'Scroll', |
20 Fling: "Fling", | 273 Fling: 'Fling', |
21 Drag: "Drag", | 274 Drag: 'Drag', |
22 Animation: "Animation", | 275 Animation: 'Animation', |
23 Uncategorized: "Uncategorized" | 276 Uncategorized: 'Uncategorized' |
24 }; | 277 }; |
25 | 278 |
26 /** | 279 /** |
27 * @enum {string} | 280 * @enum {string} |
28 */ | 281 */ |
29 WebInspector.TimelineIRModel.InputEvents = { | 282 WebInspector.TimelineIRModel.InputEvents = { |
30 Char: "Char", | 283 Char: 'Char', |
31 Click: "GestureClick", | 284 Click: 'GestureClick', |
32 ContextMenu: "ContextMenu", | 285 ContextMenu: 'ContextMenu', |
33 FlingCancel: "GestureFlingCancel", | 286 FlingCancel: 'GestureFlingCancel', |
34 FlingStart: "GestureFlingStart", | 287 FlingStart: 'GestureFlingStart', |
35 ImplSideFling: WebInspector.TimelineModel.RecordType.ImplSideFling, | 288 ImplSideFling: WebInspector.TimelineModel.RecordType.ImplSideFling, |
36 KeyDown: "KeyDown", | 289 KeyDown: 'KeyDown', |
37 KeyDownRaw: "RawKeyDown", | 290 KeyDownRaw: 'RawKeyDown', |
38 KeyUp: "KeyUp", | 291 KeyUp: 'KeyUp', |
39 LatencyScrollUpdate: "ScrollUpdate", | 292 LatencyScrollUpdate: 'ScrollUpdate', |
40 MouseDown: "MouseDown", | 293 MouseDown: 'MouseDown', |
41 MouseMove: "MouseMove", | 294 MouseMove: 'MouseMove', |
42 MouseUp: "MouseUp", | 295 MouseUp: 'MouseUp', |
43 MouseWheel: "MouseWheel", | 296 MouseWheel: 'MouseWheel', |
44 PinchBegin: "GesturePinchBegin", | 297 PinchBegin: 'GesturePinchBegin', |
45 PinchEnd: "GesturePinchEnd", | 298 PinchEnd: 'GesturePinchEnd', |
46 PinchUpdate: "GesturePinchUpdate", | 299 PinchUpdate: 'GesturePinchUpdate', |
47 ScrollBegin: "GestureScrollBegin", | 300 ScrollBegin: 'GestureScrollBegin', |
48 ScrollEnd: "GestureScrollEnd", | 301 ScrollEnd: 'GestureScrollEnd', |
49 ScrollUpdate: "GestureScrollUpdate", | 302 ScrollUpdate: 'GestureScrollUpdate', |
50 ScrollUpdateRenderer: "ScrollUpdate", | 303 ScrollUpdateRenderer: 'ScrollUpdate', |
51 ShowPress: "GestureShowPress", | 304 ShowPress: 'GestureShowPress', |
52 Tap: "GestureTap", | 305 Tap: 'GestureTap', |
53 TapCancel: "GestureTapCancel", | 306 TapCancel: 'GestureTapCancel', |
54 TapDown: "GestureTapDown", | 307 TapDown: 'GestureTapDown', |
55 TouchCancel: "TouchCancel", | 308 TouchCancel: 'TouchCancel', |
56 TouchEnd: "TouchEnd", | 309 TouchEnd: 'TouchEnd', |
57 TouchMove: "TouchMove", | 310 TouchMove: 'TouchMove', |
58 TouchStart: "TouchStart" | 311 TouchStart: 'TouchStart' |
59 }; | 312 }; |
60 | 313 |
61 WebInspector.TimelineIRModel._mergeThresholdsMs = { | 314 WebInspector.TimelineIRModel._mergeThresholdsMs = { |
62 animation: 1, | 315 animation: 1, |
63 mouse: 40, | 316 mouse: 40, |
64 }; | 317 }; |
65 | 318 |
66 WebInspector.TimelineIRModel._eventIRPhase = Symbol("eventIRPhase"); | 319 WebInspector.TimelineIRModel._eventIRPhase = Symbol('eventIRPhase'); |
67 | 320 |
68 /** | 321 |
69 * @param {!WebInspector.TracingModel.Event} event | |
70 * @return {!WebInspector.TimelineIRModel.Phases} | |
71 */ | |
72 WebInspector.TimelineIRModel.phaseForEvent = function(event) | |
73 { | |
74 return event[WebInspector.TimelineIRModel._eventIRPhase]; | |
75 }; | |
76 | |
77 WebInspector.TimelineIRModel.prototype = { | |
78 /** | |
79 * @param {?Array<!WebInspector.TracingModel.AsyncEvent>} inputLatencies | |
80 * @param {?Array<!WebInspector.TracingModel.AsyncEvent>} animations | |
81 */ | |
82 populate: function(inputLatencies, animations) | |
83 { | |
84 var eventTypes = WebInspector.TimelineIRModel.InputEvents; | |
85 var phases = WebInspector.TimelineIRModel.Phases; | |
86 | |
87 this.reset(); | |
88 if (!inputLatencies) | |
89 return; | |
90 this._processInputLatencies(inputLatencies); | |
91 if (animations) | |
92 this._processAnimations(animations); | |
93 var range = new WebInspector.SegmentedRange(); | |
94 range.appendRange(this._drags); // Drags take lower precedence than anim
ation, as we can't detect them reliably. | |
95 range.appendRange(this._cssAnimations); | |
96 range.appendRange(this._scrolls); | |
97 range.appendRange(this._responses); | |
98 this._segments = range.segments(); | |
99 }, | |
100 | |
101 /** | |
102 * @param {!Array<!WebInspector.TracingModel.AsyncEvent>} events | |
103 */ | |
104 _processInputLatencies: function(events) | |
105 { | |
106 var eventTypes = WebInspector.TimelineIRModel.InputEvents; | |
107 var phases = WebInspector.TimelineIRModel.Phases; | |
108 var thresholdsMs = WebInspector.TimelineIRModel._mergeThresholdsMs; | |
109 | |
110 var scrollStart; | |
111 var flingStart; | |
112 var touchStart; | |
113 var firstTouchMove; | |
114 var mouseWheel; | |
115 var mouseDown; | |
116 var mouseMove; | |
117 | |
118 for (var i = 0; i < events.length; ++i) { | |
119 var event = events[i]; | |
120 if (i > 0 && events[i].startTime < events[i - 1].startTime) | |
121 console.assert(false, "Unordered input events"); | |
122 var type = this._inputEventType(event.name); | |
123 switch (type) { | |
124 | |
125 case eventTypes.ScrollBegin: | |
126 this._scrolls.append(this._segmentForEvent(event, phases.Scroll)
); | |
127 scrollStart = event; | |
128 break; | |
129 | |
130 case eventTypes.ScrollEnd: | |
131 if (scrollStart) | |
132 this._scrolls.append(this._segmentForEventRange(scrollStart,
event, phases.Scroll)); | |
133 else | |
134 this._scrolls.append(this._segmentForEvent(event, phases.Scr
oll)); | |
135 scrollStart = null; | |
136 break; | |
137 | |
138 case eventTypes.ScrollUpdate: | |
139 touchStart = null; // Since we're scrolling now, disregard other
touch gestures. | |
140 this._scrolls.append(this._segmentForEvent(event, phases.Scroll)
); | |
141 break; | |
142 | |
143 case eventTypes.FlingStart: | |
144 if (flingStart) { | |
145 WebInspector.console.error(WebInspector.UIString("Two flings
at the same time? %s vs %s", flingStart.startTime, event.startTime)); | |
146 break; | |
147 } | |
148 flingStart = event; | |
149 break; | |
150 | |
151 case eventTypes.FlingCancel: | |
152 // FIXME: also process renderer fling events. | |
153 if (!flingStart) | |
154 break; | |
155 this._scrolls.append(this._segmentForEventRange(flingStart, even
t, phases.Fling)); | |
156 flingStart = null; | |
157 break; | |
158 | |
159 case eventTypes.ImplSideFling: | |
160 this._scrolls.append(this._segmentForEvent(event, phases.Fling))
; | |
161 break; | |
162 | |
163 case eventTypes.ShowPress: | |
164 case eventTypes.Tap: | |
165 case eventTypes.KeyDown: | |
166 case eventTypes.KeyDownRaw: | |
167 case eventTypes.KeyUp: | |
168 case eventTypes.Char: | |
169 case eventTypes.Click: | |
170 case eventTypes.ContextMenu: | |
171 this._responses.append(this._segmentForEvent(event, phases.Respo
nse)); | |
172 break; | |
173 | |
174 case eventTypes.TouchStart: | |
175 // We do not produce any response segment for TouchStart -- ther
e's either going to be one upon | |
176 // TouchMove for drag, or one for GestureTap. | |
177 if (touchStart) { | |
178 WebInspector.console.error(WebInspector.UIString("Two touche
s at the same time? %s vs %s", touchStart.startTime, event.startTime)); | |
179 break; | |
180 } | |
181 touchStart = event; | |
182 event.steps[0][WebInspector.TimelineIRModel._eventIRPhase] = pha
ses.Response; | |
183 firstTouchMove = null; | |
184 break; | |
185 | |
186 case eventTypes.TouchCancel: | |
187 touchStart = null; | |
188 break; | |
189 | |
190 case eventTypes.TouchMove: | |
191 if (firstTouchMove) { | |
192 this._drags.append(this._segmentForEvent(event, phases.Drag)
); | |
193 } else if (touchStart) { | |
194 firstTouchMove = event; | |
195 this._responses.append(this._segmentForEventRange(touchStart
, event, phases.Response)); | |
196 } | |
197 break; | |
198 | |
199 case eventTypes.TouchEnd: | |
200 touchStart = null; | |
201 break; | |
202 | |
203 case eventTypes.MouseDown: | |
204 mouseDown = event; | |
205 mouseMove = null; | |
206 break; | |
207 | |
208 case eventTypes.MouseMove: | |
209 if (mouseDown && !mouseMove && mouseDown.startTime + thresholdsM
s.mouse > event.startTime) { | |
210 this._responses.append(this._segmentForEvent(mouseDown, phas
es.Response)); | |
211 this._responses.append(this._segmentForEvent(event, phases.R
esponse)); | |
212 } else if (mouseDown) { | |
213 this._drags.append(this._segmentForEvent(event, phases.Drag)
); | |
214 } | |
215 mouseMove = event; | |
216 break; | |
217 | |
218 case eventTypes.MouseUp: | |
219 this._responses.append(this._segmentForEvent(event, phases.Respo
nse)); | |
220 mouseDown = null; | |
221 break; | |
222 | |
223 case eventTypes.MouseWheel: | |
224 // Do not consider first MouseWheel as trace viewer's implementa
tion does -- in case of MouseWheel it's not really special. | |
225 if (mouseWheel && canMerge(thresholdsMs.mouse, mouseWheel, event
)) | |
226 this._scrolls.append(this._segmentForEventRange(mouseWheel,
event, phases.Scroll)); | |
227 else | |
228 this._scrolls.append(this._segmentForEvent(event, phases.Scr
oll)); | |
229 mouseWheel = event; | |
230 break; | |
231 } | |
232 } | |
233 | |
234 /** | |
235 * @param {number} threshold | |
236 * @param {!WebInspector.TracingModel.AsyncEvent} first | |
237 * @param {!WebInspector.TracingModel.AsyncEvent} second | |
238 * @return {boolean} | |
239 */ | |
240 function canMerge(threshold, first, second) | |
241 { | |
242 return first.endTime < second.startTime && second.startTime < first.
endTime + threshold; | |
243 } | |
244 }, | |
245 | |
246 /** | |
247 * @param {!Array<!WebInspector.TracingModel.AsyncEvent>} events | |
248 */ | |
249 _processAnimations: function(events) | |
250 { | |
251 for (var i = 0; i < events.length; ++i) | |
252 this._cssAnimations.append(this._segmentForEvent(events[i], WebInspe
ctor.TimelineIRModel.Phases.Animation)); | |
253 }, | |
254 | |
255 /** | |
256 * @param {!WebInspector.TracingModel.AsyncEvent} event | |
257 * @param {!WebInspector.TimelineIRModel.Phases} phase | |
258 * @return {!WebInspector.Segment} | |
259 */ | |
260 _segmentForEvent: function(event, phase) | |
261 { | |
262 this._setPhaseForEvent(event, phase); | |
263 return new WebInspector.Segment(event.startTime, event.endTime, phase); | |
264 }, | |
265 | |
266 /** | |
267 * @param {!WebInspector.TracingModel.AsyncEvent} startEvent | |
268 * @param {!WebInspector.TracingModel.AsyncEvent} endEvent | |
269 * @param {!WebInspector.TimelineIRModel.Phases} phase | |
270 * @return {!WebInspector.Segment} | |
271 */ | |
272 _segmentForEventRange: function(startEvent, endEvent, phase) | |
273 { | |
274 this._setPhaseForEvent(startEvent, phase); | |
275 this._setPhaseForEvent(endEvent, phase); | |
276 return new WebInspector.Segment(startEvent.startTime, endEvent.endTime,
phase); | |
277 }, | |
278 | |
279 /** | |
280 * @param {!WebInspector.TracingModel.AsyncEvent} asyncEvent | |
281 * @param {!WebInspector.TimelineIRModel.Phases} phase | |
282 */ | |
283 _setPhaseForEvent: function(asyncEvent, phase) | |
284 { | |
285 asyncEvent.steps[0][WebInspector.TimelineIRModel._eventIRPhase] = phase; | |
286 }, | |
287 | |
288 /** | |
289 * @return {!Array<!WebInspector.Segment>} | |
290 */ | |
291 interactionRecords: function() | |
292 { | |
293 return this._segments; | |
294 }, | |
295 | |
296 reset: function() | |
297 { | |
298 var thresholdsMs = WebInspector.TimelineIRModel._mergeThresholdsMs; | |
299 | |
300 this._segments = []; | |
301 this._drags = new WebInspector.SegmentedRange(merge.bind(null, threshold
sMs.mouse)); | |
302 this._cssAnimations = new WebInspector.SegmentedRange(merge.bind(null, t
hresholdsMs.animation)); | |
303 this._responses = new WebInspector.SegmentedRange(merge.bind(null, 0)); | |
304 this._scrolls = new WebInspector.SegmentedRange(merge.bind(null, thresho
ldsMs.animation)); | |
305 | |
306 /** | |
307 * @param {number} threshold | |
308 * @param {!WebInspector.Segment} first | |
309 * @param {!WebInspector.Segment} second | |
310 */ | |
311 function merge(threshold, first, second) | |
312 { | |
313 return first.end + threshold >= second.begin && first.data === secon
d.data ? first : null; | |
314 } | |
315 }, | |
316 | |
317 /** | |
318 * @param {string} eventName | |
319 * @return {?WebInspector.TimelineIRModel.InputEvents} | |
320 */ | |
321 _inputEventType: function(eventName) | |
322 { | |
323 var prefix = "InputLatency::"; | |
324 if (!eventName.startsWith(prefix)) { | |
325 if (eventName === WebInspector.TimelineIRModel.InputEvents.ImplSideF
ling) | |
326 return /** @type {!WebInspector.TimelineIRModel.InputEvents} */
(eventName); | |
327 console.error("Unrecognized input latency event: " + eventName); | |
328 return null; | |
329 } | |
330 return /** @type {!WebInspector.TimelineIRModel.InputEvents} */ (eventNa
me.substr(prefix.length)); | |
331 } | |
332 }; | |
333 | |
OLD | NEW |