OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 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 10 matching lines...) Expand all Loading... |
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
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 | |
32 /** | 31 /** |
33 * @constructor | |
34 * @extends {WebInspector.Panel} | |
35 * @implements {WebInspector.TimelineLifecycleDelegate} | 32 * @implements {WebInspector.TimelineLifecycleDelegate} |
36 * @implements {WebInspector.TimelineModeViewDelegate} | 33 * @implements {WebInspector.TimelineModeViewDelegate} |
37 * @implements {WebInspector.Searchable} | 34 * @implements {WebInspector.Searchable} |
| 35 * @unrestricted |
38 */ | 36 */ |
39 WebInspector.TimelinePanel = function() | 37 WebInspector.TimelinePanel = class extends WebInspector.Panel { |
40 { | 38 constructor() { |
41 WebInspector.Panel.call(this, "timeline"); | 39 super('timeline'); |
42 this.registerRequiredCSS("timeline/timelinePanel.css"); | 40 this.registerRequiredCSS('timeline/timelinePanel.css'); |
43 this.element.addEventListener("contextmenu", this._contextMenu.bind(this), f
alse); | 41 this.element.addEventListener('contextmenu', this._contextMenu.bind(this), f
alse); |
44 this._dropTarget = new WebInspector.DropTarget(this.element, [WebInspector.D
ropTarget.Types.Files, WebInspector.DropTarget.Types.URIList], WebInspector.UISt
ring("Drop timeline file or URL here"), this._handleDrop.bind(this)); | 42 this._dropTarget = new WebInspector.DropTarget( |
| 43 this.element, [WebInspector.DropTarget.Types.Files, WebInspector.DropTar
get.Types.URIList], |
| 44 WebInspector.UIString('Drop timeline file or URL here'), this._handleDro
p.bind(this)); |
45 | 45 |
46 this._state = WebInspector.TimelinePanel.State.Idle; | 46 this._state = WebInspector.TimelinePanel.State.Idle; |
47 this._detailsLinkifier = new WebInspector.Linkifier(); | 47 this._detailsLinkifier = new WebInspector.Linkifier(); |
48 this._windowStartTime = 0; | 48 this._windowStartTime = 0; |
49 this._windowEndTime = Infinity; | 49 this._windowEndTime = Infinity; |
50 this._millisecondsToRecordAfterLoadEvent = 3000; | 50 this._millisecondsToRecordAfterLoadEvent = 3000; |
51 this._toggleRecordAction = /** @type {!WebInspector.Action }*/ (WebInspector
.actionRegistry.action("timeline.toggle-recording")); | 51 this._toggleRecordAction = |
| 52 /** @type {!WebInspector.Action }*/ (WebInspector.actionRegistry.action(
'timeline.toggle-recording')); |
52 this._customCPUThrottlingRate = 0; | 53 this._customCPUThrottlingRate = 0; |
53 | 54 |
54 /** @type {!Array<!WebInspector.TimelineModel.Filter>} */ | 55 /** @type {!Array<!WebInspector.TimelineModel.Filter>} */ |
55 this._filters = []; | 56 this._filters = []; |
56 if (!Runtime.experiments.isEnabled("timelineShowAllEvents")) { | 57 if (!Runtime.experiments.isEnabled('timelineShowAllEvents')) { |
57 this._filters.push(WebInspector.TimelineUIUtils.visibleEventsFilter()); | 58 this._filters.push(WebInspector.TimelineUIUtils.visibleEventsFilter()); |
58 this._filters.push(new WebInspector.ExcludeTopLevelFilter()); | 59 this._filters.push(new WebInspector.ExcludeTopLevelFilter()); |
59 } | 60 } |
60 | 61 |
61 // Create models. | 62 // Create models. |
62 this._tracingModelBackingStorage = new WebInspector.TempFileBackingStorage("
tracing"); | 63 this._tracingModelBackingStorage = new WebInspector.TempFileBackingStorage('
tracing'); |
63 this._tracingModel = new WebInspector.TracingModel(this._tracingModelBacking
Storage); | 64 this._tracingModel = new WebInspector.TracingModel(this._tracingModelBacking
Storage); |
64 this._model = new WebInspector.TimelineModel(WebInspector.TimelineUIUtils.vi
sibleEventsFilter()); | 65 this._model = new WebInspector.TimelineModel(WebInspector.TimelineUIUtils.vi
sibleEventsFilter()); |
65 this._frameModel = new WebInspector.TimelineFrameModel(event => WebInspector
.TimelineUIUtils.eventStyle(event).category.name); | 66 this._frameModel = |
| 67 new WebInspector.TimelineFrameModel(event => WebInspector.TimelineUIUtil
s.eventStyle(event).category.name); |
66 this._filmStripModel = new WebInspector.FilmStripModel(this._tracingModel); | 68 this._filmStripModel = new WebInspector.FilmStripModel(this._tracingModel); |
67 this._irModel = new WebInspector.TimelineIRModel(); | 69 this._irModel = new WebInspector.TimelineIRModel(); |
68 | 70 |
69 this._cpuThrottlingManager = new WebInspector.CPUThrottlingManager(); | 71 this._cpuThrottlingManager = new WebInspector.CPUThrottlingManager(); |
70 | 72 |
71 /** @type {!Array.<!WebInspector.TimelineModeView>} */ | 73 /** @type {!Array.<!WebInspector.TimelineModeView>} */ |
72 this._currentViews = []; | 74 this._currentViews = []; |
73 | 75 |
74 this._captureNetworkSetting = WebInspector.settings.createSetting("timelineC
aptureNetwork", false); | 76 this._captureNetworkSetting = WebInspector.settings.createSetting('timelineC
aptureNetwork', false); |
75 this._captureJSProfileSetting = WebInspector.settings.createSetting("timelin
eEnableJSSampling", true); | 77 this._captureJSProfileSetting = WebInspector.settings.createSetting('timelin
eEnableJSSampling', true); |
76 this._captureMemorySetting = WebInspector.settings.createSetting("timelineCa
ptureMemory", false); | 78 this._captureMemorySetting = WebInspector.settings.createSetting('timelineCa
ptureMemory', false); |
77 this._captureLayersAndPicturesSetting = WebInspector.settings.createSetting(
"timelineCaptureLayersAndPictures", false); | 79 this._captureLayersAndPicturesSetting = |
78 this._captureFilmStripSetting = WebInspector.settings.createSetting("timelin
eCaptureFilmStrip", false); | 80 WebInspector.settings.createSetting('timelineCaptureLayersAndPictures',
false); |
79 | 81 this._captureFilmStripSetting = WebInspector.settings.createSetting('timelin
eCaptureFilmStrip', false); |
80 this._panelToolbar = new WebInspector.Toolbar("", this.element); | 82 |
| 83 this._panelToolbar = new WebInspector.Toolbar('', this.element); |
81 this._createToolbarItems(); | 84 this._createToolbarItems(); |
82 | 85 |
83 var timelinePane = new WebInspector.VBox(); | 86 var timelinePane = new WebInspector.VBox(); |
84 timelinePane.show(this.element); | 87 timelinePane.show(this.element); |
85 var topPaneElement = timelinePane.element.createChild("div", "hbox"); | 88 var topPaneElement = timelinePane.element.createChild('div', 'hbox'); |
86 topPaneElement.id = "timeline-overview-panel"; | 89 topPaneElement.id = 'timeline-overview-panel'; |
87 | 90 |
88 // Create top overview component. | 91 // Create top overview component. |
89 this._overviewPane = new WebInspector.TimelineOverviewPane("timeline"); | 92 this._overviewPane = new WebInspector.TimelineOverviewPane('timeline'); |
90 this._overviewPane.addEventListener(WebInspector.TimelineOverviewPane.Events
.WindowChanged, this._onWindowChanged.bind(this)); | 93 this._overviewPane.addEventListener( |
| 94 WebInspector.TimelineOverviewPane.Events.WindowChanged, this._onWindowCh
anged.bind(this)); |
91 this._overviewPane.show(topPaneElement); | 95 this._overviewPane.show(topPaneElement); |
92 this._statusPaneContainer = timelinePane.element.createChild("div", "status-
pane-container fill"); | 96 this._statusPaneContainer = timelinePane.element.createChild('div', 'status-
pane-container fill'); |
93 | 97 |
94 this._createFileSelector(); | 98 this._createFileSelector(); |
95 | 99 |
96 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event
s.PageReloadRequested, this._pageReloadRequested, this); | 100 WebInspector.targetManager.addEventListener( |
| 101 WebInspector.TargetManager.Events.PageReloadRequested, this._pageReloadR
equested, this); |
97 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event
s.Load, this._loadEventFired, this); | 102 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event
s.Load, this._loadEventFired, this); |
98 | 103 |
99 // Create top level properties splitter. | 104 // Create top level properties splitter. |
100 this._detailsSplitWidget = new WebInspector.SplitWidget(false, true, "timeli
nePanelDetailsSplitViewState"); | 105 this._detailsSplitWidget = new WebInspector.SplitWidget(false, true, 'timeli
nePanelDetailsSplitViewState'); |
101 this._detailsSplitWidget.element.classList.add("timeline-details-split"); | 106 this._detailsSplitWidget.element.classList.add('timeline-details-split'); |
102 this._detailsView = new WebInspector.TimelineDetailsView(this._model, this._
filters, this); | 107 this._detailsView = new WebInspector.TimelineDetailsView(this._model, this._
filters, this); |
103 this._detailsSplitWidget.installResizer(this._detailsView.headerElement()); | 108 this._detailsSplitWidget.installResizer(this._detailsView.headerElement()); |
104 this._detailsSplitWidget.setSidebarWidget(this._detailsView); | 109 this._detailsSplitWidget.setSidebarWidget(this._detailsView); |
105 | 110 |
106 this._searchableView = new WebInspector.SearchableView(this); | 111 this._searchableView = new WebInspector.SearchableView(this); |
107 this._searchableView.setMinimumSize(0, 100); | 112 this._searchableView.setMinimumSize(0, 100); |
108 this._searchableView.element.classList.add("searchable-view"); | 113 this._searchableView.element.classList.add('searchable-view'); |
109 this._detailsSplitWidget.setMainWidget(this._searchableView); | 114 this._detailsSplitWidget.setMainWidget(this._searchableView); |
110 | 115 |
111 this._stackView = new WebInspector.StackView(false); | 116 this._stackView = new WebInspector.StackView(false); |
112 this._stackView.element.classList.add("timeline-view-stack"); | 117 this._stackView.element.classList.add('timeline-view-stack'); |
113 | 118 |
114 this._stackView.show(this._searchableView.element); | 119 this._stackView.show(this._searchableView.element); |
115 this._onModeChanged(); | 120 this._onModeChanged(); |
116 | 121 |
117 this._detailsSplitWidget.show(timelinePane.element); | 122 this._detailsSplitWidget.show(timelinePane.element); |
118 this._detailsSplitWidget.hideSidebar(); | 123 this._detailsSplitWidget.hideSidebar(); |
119 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event
s.SuspendStateChanged, this._onSuspendStateChanged, this); | 124 WebInspector.targetManager.addEventListener( |
| 125 WebInspector.TargetManager.Events.SuspendStateChanged, this._onSuspendSt
ateChanged, this); |
120 this._showRecordingHelpMessage(); | 126 this._showRecordingHelpMessage(); |
121 | 127 |
122 /** @type {!WebInspector.TracingModel.Event}|undefined */ | 128 /** @type {!WebInspector.TracingModel.Event}|undefined */ |
123 this._selectedSearchResult; | 129 this._selectedSearchResult; |
124 /** @type {!Array<!WebInspector.TracingModel.Event>}|undefined */ | 130 /** @type {!Array<!WebInspector.TracingModel.Event>}|undefined */ |
125 this._searchResults; | 131 this._searchResults; |
| 132 } |
| 133 |
| 134 /** |
| 135 * @return {!WebInspector.TimelinePanel} |
| 136 */ |
| 137 static instance() { |
| 138 return /** @type {!WebInspector.TimelinePanel} */ (self.runtime.sharedInstan
ce(WebInspector.TimelinePanel)); |
| 139 } |
| 140 |
| 141 /** |
| 142 * @override |
| 143 * @return {?WebInspector.SearchableView} |
| 144 */ |
| 145 searchableView() { |
| 146 return this._searchableView; |
| 147 } |
| 148 |
| 149 /** |
| 150 * @override |
| 151 */ |
| 152 wasShown() { |
| 153 WebInspector.context.setFlavor(WebInspector.TimelinePanel, this); |
| 154 } |
| 155 |
| 156 /** |
| 157 * @override |
| 158 */ |
| 159 willHide() { |
| 160 WebInspector.context.setFlavor(WebInspector.TimelinePanel, null); |
| 161 } |
| 162 |
| 163 /** |
| 164 * @return {number} |
| 165 */ |
| 166 windowStartTime() { |
| 167 if (this._windowStartTime) |
| 168 return this._windowStartTime; |
| 169 return this._model.minimumRecordTime(); |
| 170 } |
| 171 |
| 172 /** |
| 173 * @return {number} |
| 174 */ |
| 175 windowEndTime() { |
| 176 if (this._windowEndTime < Infinity) |
| 177 return this._windowEndTime; |
| 178 return this._model.maximumRecordTime() || Infinity; |
| 179 } |
| 180 |
| 181 /** |
| 182 * @param {!WebInspector.Event} event |
| 183 */ |
| 184 _onWindowChanged(event) { |
| 185 this._windowStartTime = event.data.startTime; |
| 186 this._windowEndTime = event.data.endTime; |
| 187 |
| 188 for (var i = 0; i < this._currentViews.length; ++i) |
| 189 this._currentViews[i].setWindowTimes(this._windowStartTime, this._windowEn
dTime); |
| 190 |
| 191 if (!this._selection || this._selection.type() === WebInspector.TimelineSele
ction.Type.Range) |
| 192 this.select(null); |
| 193 } |
| 194 |
| 195 /** |
| 196 * @param {!WebInspector.Event} event |
| 197 */ |
| 198 _onOverviewSelectionChanged(event) { |
| 199 var selection = /** @type {!WebInspector.TimelineSelection} */ (event.data); |
| 200 this.select(selection); |
| 201 } |
| 202 |
| 203 /** |
| 204 * @override |
| 205 * @param {number} windowStartTime |
| 206 * @param {number} windowEndTime |
| 207 */ |
| 208 requestWindowTimes(windowStartTime, windowEndTime) { |
| 209 this._overviewPane.requestWindowTimes(windowStartTime, windowEndTime); |
| 210 } |
| 211 |
| 212 /** |
| 213 * @return {!WebInspector.Widget} |
| 214 */ |
| 215 _layersView() { |
| 216 if (this._lazyLayersView) |
| 217 return this._lazyLayersView; |
| 218 this._lazyLayersView = |
| 219 new WebInspector.TimelineLayersView(this._model, this._showSnapshotInPai
ntProfiler.bind(this)); |
| 220 return this._lazyLayersView; |
| 221 } |
| 222 |
| 223 _paintProfilerView() { |
| 224 if (this._lazyPaintProfilerView) |
| 225 return this._lazyPaintProfilerView; |
| 226 this._lazyPaintProfilerView = new WebInspector.TimelinePaintProfilerView(thi
s._frameModel); |
| 227 return this._lazyPaintProfilerView; |
| 228 } |
| 229 |
| 230 /** |
| 231 * @param {!WebInspector.TimelineModeView} modeView |
| 232 */ |
| 233 _addModeView(modeView) { |
| 234 modeView.setWindowTimes(this.windowStartTime(), this.windowEndTime()); |
| 235 modeView.refreshRecords(); |
| 236 var splitWidget = |
| 237 this._stackView.appendView(modeView.view(), 'timelinePanelTimelineStackS
plitViewState', undefined, 112); |
| 238 var resizer = modeView.resizerElement(); |
| 239 if (splitWidget && resizer) { |
| 240 splitWidget.hideDefaultResizer(); |
| 241 splitWidget.installResizer(resizer); |
| 242 } |
| 243 this._currentViews.push(modeView); |
| 244 } |
| 245 |
| 246 _removeAllModeViews() { |
| 247 this._currentViews.forEach(view => view.dispose()); |
| 248 this._currentViews = []; |
| 249 this._stackView.detachChildWidgets(); |
| 250 } |
| 251 |
| 252 /** |
| 253 * @param {!WebInspector.TimelinePanel.State} state |
| 254 */ |
| 255 _setState(state) { |
| 256 this._state = state; |
| 257 this._updateTimelineControls(); |
| 258 } |
| 259 |
| 260 /** |
| 261 * @param {string} name |
| 262 * @param {!WebInspector.Setting} setting |
| 263 * @param {string} tooltip |
| 264 * @return {!WebInspector.ToolbarItem} |
| 265 */ |
| 266 _createSettingCheckbox(name, setting, tooltip) { |
| 267 if (!this._recordingOptionUIControls) |
| 268 this._recordingOptionUIControls = []; |
| 269 var checkboxItem = new WebInspector.ToolbarCheckbox(name, tooltip, setting); |
| 270 this._recordingOptionUIControls.push(checkboxItem); |
| 271 return checkboxItem; |
| 272 } |
| 273 |
| 274 _createToolbarItems() { |
| 275 this._panelToolbar.removeToolbarItems(); |
| 276 |
| 277 var perspectiveSetting = |
| 278 WebInspector.settings.createSetting('timelinePerspective', WebInspector.
TimelinePanel.Perspectives.Load); |
| 279 if (Runtime.experiments.isEnabled('timelineRecordingPerspectives')) { |
| 280 /** |
| 281 * @this {!WebInspector.TimelinePanel} |
| 282 */ |
| 283 function onPerspectiveChanged() { |
| 284 perspectiveSetting.set(perspectiveCombobox.selectElement().value); |
| 285 this._createToolbarItems(); |
| 286 } |
| 287 |
| 288 /** |
| 289 * @param {string} id |
| 290 * @param {string} title |
| 291 */ |
| 292 function addPerspectiveOption(id, title) { |
| 293 var option = perspectiveCombobox.createOption(title, '', id); |
| 294 perspectiveCombobox.addOption(option); |
| 295 if (id === perspectiveSetting.get()) |
| 296 perspectiveCombobox.select(option); |
| 297 } |
| 298 |
| 299 var perspectiveCombobox = new WebInspector.ToolbarComboBox(onPerspectiveCh
anged.bind(this)); |
| 300 addPerspectiveOption(WebInspector.TimelinePanel.Perspectives.Load, WebInsp
ector.UIString('Page Load')); |
| 301 addPerspectiveOption( |
| 302 WebInspector.TimelinePanel.Perspectives.Responsiveness, WebInspector.U
IString('Responsiveness')); |
| 303 addPerspectiveOption(WebInspector.TimelinePanel.Perspectives.Custom, WebIn
spector.UIString('Custom')); |
| 304 this._panelToolbar.appendToolbarItem(perspectiveCombobox); |
| 305 |
| 306 switch (perspectiveSetting.get()) { |
| 307 case WebInspector.TimelinePanel.Perspectives.Load: |
| 308 this._captureNetworkSetting.set(true); |
| 309 this._captureJSProfileSetting.set(true); |
| 310 this._captureMemorySetting.set(false); |
| 311 this._captureLayersAndPicturesSetting.set(false); |
| 312 this._captureFilmStripSetting.set(true); |
| 313 break; |
| 314 case WebInspector.TimelinePanel.Perspectives.Responsiveness: |
| 315 this._captureNetworkSetting.set(true); |
| 316 this._captureJSProfileSetting.set(true); |
| 317 this._captureMemorySetting.set(false); |
| 318 this._captureLayersAndPicturesSetting.set(false); |
| 319 this._captureFilmStripSetting.set(false); |
| 320 break; |
| 321 } |
| 322 } |
| 323 if (Runtime.experiments.isEnabled('timelineRecordingPerspectives') && |
| 324 perspectiveSetting.get() === WebInspector.TimelinePanel.Perspectives.Loa
d) { |
| 325 this._reloadButton = |
| 326 new WebInspector.ToolbarButton(WebInspector.UIString('Record & Reload'
), 'refresh-toolbar-item'); |
| 327 this._reloadButton.addEventListener('click', () => WebInspector.targetMana
ger.reloadPage()); |
| 328 this._panelToolbar.appendToolbarItem(this._reloadButton); |
| 329 } else { |
| 330 this._panelToolbar.appendToolbarItem(WebInspector.Toolbar.createActionButt
on(this._toggleRecordAction)); |
| 331 } |
| 332 |
| 333 this._updateTimelineControls(); |
| 334 var clearButton = new WebInspector.ToolbarButton(WebInspector.UIString('Clea
r recording'), 'clear-toolbar-item'); |
| 335 clearButton.addEventListener('click', this._clear, this); |
| 336 this._panelToolbar.appendToolbarItem(clearButton); |
| 337 |
| 338 this._panelToolbar.appendSeparator(); |
| 339 |
| 340 this._panelToolbar.appendText(WebInspector.UIString('Capture:')); |
| 341 |
| 342 var screenshotCheckbox = this._createSettingCheckbox( |
| 343 WebInspector.UIString('Screenshots'), this._captureFilmStripSetting, |
| 344 WebInspector.UIString('Capture screenshots while recording. (Has small p
erformance overhead)')); |
| 345 |
| 346 if (!Runtime.experiments.isEnabled('timelineRecordingPerspectives') || |
| 347 perspectiveSetting.get() === WebInspector.TimelinePanel.Perspectives.Cus
tom) { |
| 348 this._panelToolbar.appendToolbarItem(this._createSettingCheckbox( |
| 349 WebInspector.UIString('Network'), this._captureNetworkSetting, |
| 350 WebInspector.UIString('Show network requests information'))); |
| 351 this._panelToolbar.appendToolbarItem(this._createSettingCheckbox( |
| 352 WebInspector.UIString('JS Profile'), this._captureJSProfileSetting, |
| 353 WebInspector.UIString('Capture JavaScript stacks with sampling profile
r. (Has small performance overhead)'))); |
| 354 this._panelToolbar.appendToolbarItem(screenshotCheckbox); |
| 355 this._panelToolbar.appendToolbarItem(this._createSettingCheckbox( |
| 356 WebInspector.UIString('Memory'), this._captureMemorySetting, |
| 357 WebInspector.UIString('Capture memory information on every timeline ev
ent.'))); |
| 358 this._panelToolbar.appendToolbarItem(this._createSettingCheckbox( |
| 359 WebInspector.UIString('Paint'), this._captureLayersAndPicturesSetting, |
| 360 WebInspector.UIString( |
| 361 'Capture graphics layer positions and rasterization draw calls. (H
as large performance overhead)'))); |
| 362 } else { |
| 363 this._panelToolbar.appendToolbarItem(screenshotCheckbox); |
| 364 } |
| 365 |
| 366 this._captureNetworkSetting.addChangeListener(this._onNetworkChanged, this); |
| 367 this._captureMemorySetting.addChangeListener(this._onModeChanged, this); |
| 368 this._captureFilmStripSetting.addChangeListener(this._onModeChanged, this); |
| 369 |
| 370 this._panelToolbar.appendSeparator(); |
| 371 var garbageCollectButton = |
| 372 new WebInspector.ToolbarButton(WebInspector.UIString('Collect garbage'),
'garbage-collect-toolbar-item'); |
| 373 garbageCollectButton.addEventListener('click', this._garbageCollectButtonCli
cked, this); |
| 374 this._panelToolbar.appendToolbarItem(garbageCollectButton); |
| 375 |
| 376 this._panelToolbar.appendSeparator(); |
| 377 this._cpuThrottlingCombobox = new WebInspector.ToolbarComboBox(this._onCPUTh
rottlingChanged.bind(this)); |
| 378 this._panelToolbar.appendToolbarItem(this._cpuThrottlingCombobox); |
| 379 this._populateCPUThrottingCombobox(); |
| 380 } |
| 381 |
| 382 _populateCPUThrottingCombobox() { |
| 383 var cpuThrottlingCombobox = this._cpuThrottlingCombobox; |
| 384 cpuThrottlingCombobox.removeOptions(); |
| 385 var currentRate = this._cpuThrottlingManager.rate(); |
| 386 var hasSelection = false; |
| 387 /** |
| 388 * @param {string} name |
| 389 * @param {number} value |
| 390 */ |
| 391 function addGroupingOption(name, value) { |
| 392 var option = cpuThrottlingCombobox.createOption(name, '', String(value)); |
| 393 cpuThrottlingCombobox.addOption(option); |
| 394 if (hasSelection || (value && value !== currentRate)) |
| 395 return; |
| 396 cpuThrottlingCombobox.select(option); |
| 397 hasSelection = true; |
| 398 } |
| 399 var predefinedRates = new Map([ |
| 400 [1, WebInspector.UIString('No CPU throttling')], [2, WebInspector.UIString
('High end device (2\xD7 slowdown)')], |
| 401 [5, WebInspector.UIString('Low end device (5\xD7 slowdown)')] |
| 402 ]); |
| 403 for (var rate of predefinedRates) |
| 404 addGroupingOption(rate[1], rate[0]); |
| 405 if (this._customCPUThrottlingRate && !predefinedRates.has(this._customCPUThr
ottlingRate)) |
| 406 addGroupingOption( |
| 407 WebInspector.UIString('Custom rate (%d\xD7 slowdown)', this._customCPU
ThrottlingRate), |
| 408 this._customCPUThrottlingRate); |
| 409 addGroupingOption(WebInspector.UIString('Set custom rate\u2026'), 0); |
| 410 } |
| 411 |
| 412 _prepareToLoadTimeline() { |
| 413 console.assert(this._state === WebInspector.TimelinePanel.State.Idle); |
| 414 this._setState(WebInspector.TimelinePanel.State.Loading); |
| 415 } |
| 416 |
| 417 _createFileSelector() { |
| 418 if (this._fileSelectorElement) |
| 419 this._fileSelectorElement.remove(); |
| 420 this._fileSelectorElement = WebInspector.createFileSelectorElement(this._loa
dFromFile.bind(this)); |
| 421 this.element.appendChild(this._fileSelectorElement); |
| 422 } |
| 423 |
| 424 /** |
| 425 * @param {!Event} event |
| 426 */ |
| 427 _contextMenu(event) { |
| 428 var contextMenu = new WebInspector.ContextMenu(event); |
| 429 contextMenu.appendItemsAtLocation('timelineMenu'); |
| 430 contextMenu.show(); |
| 431 } |
| 432 |
| 433 /** |
| 434 * @return {boolean} |
| 435 */ |
| 436 _saveToFile() { |
| 437 if (this._state !== WebInspector.TimelinePanel.State.Idle) |
| 438 return true; |
| 439 if (this._model.isEmpty()) |
| 440 return true; |
| 441 |
| 442 var now = new Date(); |
| 443 var fileName = 'TimelineRawData-' + now.toISO8601Compact() + '.json'; |
| 444 var stream = new WebInspector.FileOutputStream(); |
| 445 |
| 446 /** |
| 447 * @param {boolean} accepted |
| 448 * @this {WebInspector.TimelinePanel} |
| 449 */ |
| 450 function callback(accepted) { |
| 451 if (!accepted) |
| 452 return; |
| 453 var saver = new WebInspector.TracingTimelineSaver(); |
| 454 this._tracingModelBackingStorage.writeToStream(stream, saver); |
| 455 } |
| 456 stream.open(fileName, callback.bind(this)); |
| 457 return true; |
| 458 } |
| 459 |
| 460 /** |
| 461 * @return {boolean} |
| 462 */ |
| 463 _selectFileToLoad() { |
| 464 this._fileSelectorElement.click(); |
| 465 return true; |
| 466 } |
| 467 |
| 468 /** |
| 469 * @param {!File} file |
| 470 */ |
| 471 _loadFromFile(file) { |
| 472 if (this._state !== WebInspector.TimelinePanel.State.Idle) |
| 473 return; |
| 474 this._prepareToLoadTimeline(); |
| 475 this._loader = WebInspector.TimelineLoader.loadFromFile(this._tracingModel,
file, this); |
| 476 this._createFileSelector(); |
| 477 } |
| 478 |
| 479 /** |
| 480 * @param {string} url |
| 481 */ |
| 482 _loadFromURL(url) { |
| 483 if (this._state !== WebInspector.TimelinePanel.State.Idle) |
| 484 return; |
| 485 this._prepareToLoadTimeline(); |
| 486 this._loader = WebInspector.TimelineLoader.loadFromURL(this._tracingModel, u
rl, this); |
| 487 } |
| 488 |
| 489 _refreshViews() { |
| 490 for (var i = 0; i < this._currentViews.length; ++i) { |
| 491 var view = this._currentViews[i]; |
| 492 view.refreshRecords(); |
| 493 } |
| 494 this._updateSelectionDetails(); |
| 495 } |
| 496 |
| 497 _onModeChanged() { |
| 498 // Set up overview controls. |
| 499 this._overviewControls = []; |
| 500 this._overviewControls.push(new WebInspector.TimelineEventOverviewResponsive
ness(this._model, this._frameModel)); |
| 501 if (Runtime.experiments.isEnabled('inputEventsOnTimelineOverview')) |
| 502 this._overviewControls.push(new WebInspector.TimelineEventOverviewInput(th
is._model)); |
| 503 this._overviewControls.push(new WebInspector.TimelineEventOverviewFrames(thi
s._model, this._frameModel)); |
| 504 this._overviewControls.push(new WebInspector.TimelineEventOverviewCPUActivit
y(this._model)); |
| 505 this._overviewControls.push(new WebInspector.TimelineEventOverviewNetwork(th
is._model)); |
| 506 if (this._captureFilmStripSetting.get()) |
| 507 this._overviewControls.push(new WebInspector.TimelineFilmStripOverview(thi
s._model, this._filmStripModel)); |
| 508 if (this._captureMemorySetting.get()) |
| 509 this._overviewControls.push(new WebInspector.TimelineEventOverviewMemory(t
his._model)); |
| 510 this._overviewPane.setOverviewControls(this._overviewControls); |
| 511 |
| 512 // Set up the main view. |
| 513 this._removeAllModeViews(); |
| 514 this._flameChart = |
| 515 new WebInspector.TimelineFlameChartView(this, this._model, this._frameMo
del, this._irModel, this._filters); |
| 516 this._flameChart.enableNetworkPane(this._captureNetworkSetting.get()); |
| 517 this._addModeView(this._flameChart); |
| 518 |
| 519 if (this._captureMemorySetting.get()) |
| 520 this._addModeView(new WebInspector.MemoryCountersGraph( |
| 521 this, this._model, [WebInspector.TimelineUIUtils.visibleEventsFilter()
])); |
| 522 |
| 523 this.doResize(); |
| 524 this.select(null); |
| 525 } |
| 526 |
| 527 _onNetworkChanged() { |
| 528 if (this._flameChart) |
| 529 this._flameChart.enableNetworkPane(this._captureNetworkSetting.get(), true
); |
| 530 } |
| 531 |
| 532 _onCPUThrottlingChanged() { |
| 533 if (!this._cpuThrottlingManager) |
| 534 return; |
| 535 var value = this._cpuThrottlingCombobox.selectedOption().value; |
| 536 var isLastOption = this._cpuThrottlingCombobox.selectedIndex() === this._cpu
ThrottlingCombobox.size() - 1; |
| 537 this._populateCPUThrottingCombobox(); |
| 538 var resultPromise = isLastOption ? |
| 539 WebInspector.TimelinePanel.CustomCPUThrottlingRateDialog.show(this._cpuT
hrottlingCombobox.element) : |
| 540 Promise.resolve(value); |
| 541 resultPromise.then(text => { |
| 542 var value = Number.parseFloat(text); |
| 543 if (value >= 1) { |
| 544 if (isLastOption) |
| 545 this._customCPUThrottlingRate = value; |
| 546 this._cpuThrottlingManager.setRate(value); |
| 547 this._populateCPUThrottingCombobox(); |
| 548 } |
| 549 }); |
| 550 } |
| 551 |
| 552 /** |
| 553 * @param {boolean} enabled |
| 554 */ |
| 555 _setUIControlsEnabled(enabled) { |
| 556 /** |
| 557 * @param {!WebInspector.ToolbarButton} toolbarButton |
| 558 */ |
| 559 function handler(toolbarButton) { |
| 560 toolbarButton.setEnabled(enabled); |
| 561 } |
| 562 this._recordingOptionUIControls.forEach(handler); |
| 563 } |
| 564 |
| 565 /** |
| 566 * @param {boolean} userInitiated |
| 567 */ |
| 568 _startRecording(userInitiated) { |
| 569 console.assert(!this._statusPane, 'Status pane is already opened.'); |
| 570 var mainTarget = WebInspector.targetManager.mainTarget(); |
| 571 if (!mainTarget) |
| 572 return; |
| 573 this._setState(WebInspector.TimelinePanel.State.StartPending); |
| 574 this._showRecordingStarted(); |
| 575 |
| 576 this._autoRecordGeneration = userInitiated ? null : Symbol('Generation'); |
| 577 this._controller = new WebInspector.TimelineController(mainTarget, this, thi
s._tracingModel); |
| 578 this._controller.startRecording( |
| 579 true, this._captureJSProfileSetting.get(), this._captureMemorySetting.ge
t(), |
| 580 this._captureLayersAndPicturesSetting.get(), |
| 581 this._captureFilmStripSetting && this._captureFilmStripSetting.get()); |
| 582 |
| 583 for (var i = 0; i < this._overviewControls.length; ++i) |
| 584 this._overviewControls[i].timelineStarted(); |
| 585 |
| 586 if (userInitiated) |
| 587 WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.Timel
ineStarted); |
| 588 this._setUIControlsEnabled(false); |
| 589 this._hideRecordingHelpMessage(); |
| 590 } |
| 591 |
| 592 _stopRecording() { |
| 593 if (this._statusPane) { |
| 594 this._statusPane.finish(); |
| 595 this._statusPane.updateStatus(WebInspector.UIString('Stopping timeline\u20
26')); |
| 596 this._statusPane.updateProgressBar(WebInspector.UIString('Received'), 0); |
| 597 } |
| 598 this._setState(WebInspector.TimelinePanel.State.StopPending); |
| 599 this._autoRecordGeneration = null; |
| 600 this._controller.stopRecording(); |
| 601 this._controller = null; |
| 602 this._setUIControlsEnabled(true); |
| 603 } |
| 604 |
| 605 _onSuspendStateChanged() { |
| 606 this._updateTimelineControls(); |
| 607 } |
| 608 |
| 609 _updateTimelineControls() { |
| 610 var state = WebInspector.TimelinePanel.State; |
| 611 this._toggleRecordAction.setToggled(this._state === state.Recording); |
| 612 this._toggleRecordAction.setEnabled(this._state === state.Recording || this.
_state === state.Idle); |
| 613 this._panelToolbar.setEnabled(this._state !== state.Loading); |
| 614 this._dropTarget.setEnabled(this._state === state.Idle); |
| 615 } |
| 616 |
| 617 _toggleRecording() { |
| 618 if (this._state === WebInspector.TimelinePanel.State.Idle) |
| 619 this._startRecording(true); |
| 620 else if (this._state === WebInspector.TimelinePanel.State.Recording) |
| 621 this._stopRecording(); |
| 622 } |
| 623 |
| 624 _garbageCollectButtonClicked() { |
| 625 var targets = WebInspector.targetManager.targets(); |
| 626 for (var i = 0; i < targets.length; ++i) |
| 627 targets[i].heapProfilerAgent().collectGarbage(); |
| 628 } |
| 629 |
| 630 _clear() { |
| 631 WebInspector.LineLevelProfile.instance().reset(); |
| 632 this._tracingModel.reset(); |
| 633 this._model.reset(); |
| 634 this._showRecordingHelpMessage(); |
| 635 |
| 636 this.requestWindowTimes(0, Infinity); |
| 637 delete this._selection; |
| 638 this._frameModel.reset(); |
| 639 this._filmStripModel.reset(this._tracingModel); |
| 640 this._overviewPane.reset(); |
| 641 for (var i = 0; i < this._currentViews.length; ++i) |
| 642 this._currentViews[i].reset(); |
| 643 for (var i = 0; i < this._overviewControls.length; ++i) |
| 644 this._overviewControls[i].reset(); |
| 645 this.select(null); |
| 646 this._detailsSplitWidget.hideSidebar(); |
| 647 } |
| 648 |
| 649 /** |
| 650 * @override |
| 651 */ |
| 652 recordingStarted() { |
| 653 this._clear(); |
| 654 this._setState(WebInspector.TimelinePanel.State.Recording); |
| 655 this._showRecordingStarted(); |
| 656 this._statusPane.updateStatus(WebInspector.UIString('Recording\u2026')); |
| 657 this._statusPane.updateProgressBar(WebInspector.UIString('Buffer usage'), 0)
; |
| 658 this._statusPane.startTimer(); |
| 659 this._hideRecordingHelpMessage(); |
| 660 } |
| 661 |
| 662 /** |
| 663 * @override |
| 664 * @param {number} usage |
| 665 */ |
| 666 recordingProgress(usage) { |
| 667 this._statusPane.updateProgressBar(WebInspector.UIString('Buffer usage'), us
age * 100); |
| 668 } |
| 669 |
| 670 _showRecordingHelpMessage() { |
| 671 /** |
| 672 * @param {string} tagName |
| 673 * @param {string} contents |
| 674 * @return {!Element} |
| 675 */ |
| 676 function encloseWithTag(tagName, contents) { |
| 677 var e = createElement(tagName); |
| 678 e.textContent = contents; |
| 679 return e; |
| 680 } |
| 681 |
| 682 var recordNode = encloseWithTag( |
| 683 'b', WebInspector.shortcutRegistry.shortcutDescriptorsForAction('timelin
e.toggle-recording')[0].name); |
| 684 var reloadNode = |
| 685 encloseWithTag('b', WebInspector.shortcutRegistry.shortcutDescriptorsFor
Action('main.reload')[0].name); |
| 686 var navigateNode = encloseWithTag('b', WebInspector.UIString('WASD (ZQSD)'))
; |
| 687 var hintText = createElementWithClass('div'); |
| 688 hintText.appendChild(WebInspector.formatLocalized( |
| 689 'To capture a new timeline, click the record toolbar button or hit %s.',
[recordNode])); |
| 690 hintText.createChild('br'); |
| 691 hintText.appendChild( |
| 692 WebInspector.formatLocalized('To evaluate page load performance, hit %s
to record the reload.', [reloadNode])); |
| 693 hintText.createChild('p'); |
| 694 hintText.appendChild( |
| 695 WebInspector.formatLocalized('After recording, select an area of interes
t in the overview by dragging.', [])); |
| 696 hintText.createChild('br'); |
| 697 hintText.appendChild(WebInspector.formatLocalized( |
| 698 'Then, zoom and pan the timeline with the mousewheel and %s keys.', [nav
igateNode])); |
| 699 this._hideRecordingHelpMessage(); |
| 700 this._helpMessageElement = |
| 701 this._searchableView.element.createChild('div', 'full-widget-dimmed-bann
er timeline-status-pane'); |
| 702 this._helpMessageElement.appendChild(hintText); |
| 703 } |
| 704 |
| 705 _hideRecordingHelpMessage() { |
| 706 if (this._helpMessageElement) |
| 707 this._helpMessageElement.remove(); |
| 708 delete this._helpMessageElement; |
| 709 } |
| 710 |
| 711 /** |
| 712 * @override |
| 713 */ |
| 714 loadingStarted() { |
| 715 this._hideRecordingHelpMessage(); |
| 716 |
| 717 if (this._statusPane) |
| 718 this._statusPane.hide(); |
| 719 this._statusPane = new WebInspector.TimelinePanel.StatusPane(false, this._ca
ncelLoading.bind(this)); |
| 720 this._statusPane.showPane(this._statusPaneContainer); |
| 721 this._statusPane.updateStatus(WebInspector.UIString('Loading timeline\u2026'
)); |
| 722 // FIXME: make loading from backend cancelable as well. |
| 723 if (!this._loader) |
| 724 this._statusPane.finish(); |
| 725 this.loadingProgress(0); |
| 726 } |
| 727 |
| 728 /** |
| 729 * @override |
| 730 * @param {number=} progress |
| 731 */ |
| 732 loadingProgress(progress) { |
| 733 if (typeof progress === 'number') |
| 734 this._statusPane.updateProgressBar(WebInspector.UIString('Received'), prog
ress * 100); |
| 735 } |
| 736 |
| 737 /** |
| 738 * @override |
| 739 * @param {boolean} success |
| 740 */ |
| 741 loadingComplete(success) { |
| 742 var loadedFromFile = !!this._loader; |
| 743 delete this._loader; |
| 744 this._setState(WebInspector.TimelinePanel.State.Idle); |
| 745 |
| 746 if (!success) { |
| 747 this._statusPane.hide(); |
| 748 delete this._statusPane; |
| 749 this._clear(); |
| 750 return; |
| 751 } |
| 752 |
| 753 if (this._statusPane) |
| 754 this._statusPane.updateStatus(WebInspector.UIString('Processing timeline\u
2026')); |
| 755 this._model.setEvents(this._tracingModel, loadedFromFile); |
| 756 this._frameModel.reset(); |
| 757 this._frameModel.addTraceEvents( |
| 758 WebInspector.targetManager.mainTarget(), this._model.inspectedTargetEven
ts(), this._model.sessionId() || ''); |
| 759 this._filmStripModel.reset(this._tracingModel); |
| 760 var groups = WebInspector.TimelineModel.AsyncEventGroup; |
| 761 var asyncEventsByGroup = this._model.mainThreadAsyncEvents(); |
| 762 this._irModel.populate(asyncEventsByGroup.get(groups.input), asyncEventsByGr
oup.get(groups.animation)); |
| 763 this._model.cpuProfiles().forEach(profile => WebInspector.LineLevelProfile.i
nstance().appendCPUProfile(profile)); |
| 764 if (this._statusPane) |
| 765 this._statusPane.hide(); |
| 766 delete this._statusPane; |
| 767 this._overviewPane.reset(); |
| 768 this._overviewPane.setBounds(this._model.minimumRecordTime(), this._model.ma
ximumRecordTime()); |
| 769 this._setAutoWindowTimes(); |
| 770 this._refreshViews(); |
| 771 for (var i = 0; i < this._overviewControls.length; ++i) |
| 772 this._overviewControls[i].timelineStopped(); |
| 773 this._setMarkers(); |
| 774 this._overviewPane.scheduleUpdate(); |
| 775 this._updateSearchHighlight(false, true); |
| 776 this._detailsSplitWidget.showBoth(); |
| 777 } |
| 778 |
| 779 _showRecordingStarted() { |
| 780 if (this._statusPane) |
| 781 return; |
| 782 this._statusPane = new WebInspector.TimelinePanel.StatusPane(true, this._sto
pRecording.bind(this)); |
| 783 this._statusPane.showPane(this._statusPaneContainer); |
| 784 this._statusPane.updateStatus(WebInspector.UIString('Initializing recording\
u2026')); |
| 785 } |
| 786 |
| 787 _cancelLoading() { |
| 788 if (this._loader) |
| 789 this._loader.cancel(); |
| 790 } |
| 791 |
| 792 _setMarkers() { |
| 793 var markers = new Map(); |
| 794 var recordTypes = WebInspector.TimelineModel.RecordType; |
| 795 var zeroTime = this._model.minimumRecordTime(); |
| 796 for (var record of this._model.eventDividerRecords()) { |
| 797 if (record.type() === recordTypes.TimeStamp || record.type() === recordTyp
es.ConsoleTime) |
| 798 continue; |
| 799 markers.set(record.startTime(), WebInspector.TimelineUIUtils.createDivider
ForRecord(record, zeroTime, 0)); |
| 800 } |
| 801 this._overviewPane.setMarkers(markers); |
| 802 } |
| 803 |
| 804 /** |
| 805 * @param {!WebInspector.Event} event |
| 806 */ |
| 807 _pageReloadRequested(event) { |
| 808 if (this._state !== WebInspector.TimelinePanel.State.Idle || !this.isShowing
()) |
| 809 return; |
| 810 this._startRecording(false); |
| 811 } |
| 812 |
| 813 /** |
| 814 * @param {!WebInspector.Event} event |
| 815 */ |
| 816 _loadEventFired(event) { |
| 817 if (this._state !== WebInspector.TimelinePanel.State.Recording || !this._aut
oRecordGeneration) |
| 818 return; |
| 819 setTimeout(stopRecordingOnReload.bind(this, this._autoRecordGeneration), thi
s._millisecondsToRecordAfterLoadEvent); |
| 820 |
| 821 /** |
| 822 * @this {WebInspector.TimelinePanel} |
| 823 * @param {!Object} recordGeneration |
| 824 */ |
| 825 function stopRecordingOnReload(recordGeneration) { |
| 826 // Check if we're still in the same recording session. |
| 827 if (this._state !== WebInspector.TimelinePanel.State.Recording || this._au
toRecordGeneration !== recordGeneration) |
| 828 return; |
| 829 this._stopRecording(); |
| 830 } |
| 831 } |
| 832 |
| 833 // WebInspector.Searchable implementation |
| 834 |
| 835 /** |
| 836 * @override |
| 837 */ |
| 838 jumpToNextSearchResult() { |
| 839 if (!this._searchResults || !this._searchResults.length) |
| 840 return; |
| 841 var index = this._selectedSearchResult ? this._searchResults.indexOf(this._s
electedSearchResult) : -1; |
| 842 this._jumpToSearchResult(index + 1); |
| 843 } |
| 844 |
| 845 /** |
| 846 * @override |
| 847 */ |
| 848 jumpToPreviousSearchResult() { |
| 849 if (!this._searchResults || !this._searchResults.length) |
| 850 return; |
| 851 var index = this._selectedSearchResult ? this._searchResults.indexOf(this._s
electedSearchResult) : 0; |
| 852 this._jumpToSearchResult(index - 1); |
| 853 } |
| 854 |
| 855 /** |
| 856 * @override |
| 857 * @return {boolean} |
| 858 */ |
| 859 supportsCaseSensitiveSearch() { |
| 860 return false; |
| 861 } |
| 862 |
| 863 /** |
| 864 * @override |
| 865 * @return {boolean} |
| 866 */ |
| 867 supportsRegexSearch() { |
| 868 return false; |
| 869 } |
| 870 |
| 871 /** |
| 872 * @param {number} index |
| 873 */ |
| 874 _jumpToSearchResult(index) { |
| 875 this._selectSearchResult((index + this._searchResults.length) % this._search
Results.length); |
| 876 this._currentViews[0].highlightSearchResult(this._selectedSearchResult, this
._searchRegex, true); |
| 877 } |
| 878 |
| 879 /** |
| 880 * @param {number} index |
| 881 */ |
| 882 _selectSearchResult(index) { |
| 883 this._selectedSearchResult = this._searchResults[index]; |
| 884 this._searchableView.updateCurrentMatchIndex(index); |
| 885 } |
| 886 |
| 887 _clearHighlight() { |
| 888 this._currentViews[0].highlightSearchResult(null); |
| 889 } |
| 890 |
| 891 /** |
| 892 * @param {boolean} revealRecord |
| 893 * @param {boolean} shouldJump |
| 894 * @param {boolean=} jumpBackwards |
| 895 */ |
| 896 _updateSearchHighlight(revealRecord, shouldJump, jumpBackwards) { |
| 897 if (!this._searchRegex) { |
| 898 this._clearHighlight(); |
| 899 return; |
| 900 } |
| 901 |
| 902 if (!this._searchResults) |
| 903 this._updateSearchResults(shouldJump, jumpBackwards); |
| 904 this._currentViews[0].highlightSearchResult(this._selectedSearchResult, this
._searchRegex, revealRecord); |
| 905 } |
| 906 |
| 907 /** |
| 908 * @param {boolean} shouldJump |
| 909 * @param {boolean=} jumpBackwards |
| 910 */ |
| 911 _updateSearchResults(shouldJump, jumpBackwards) { |
| 912 if (!this._searchRegex) |
| 913 return; |
| 914 |
| 915 // FIXME: search on all threads. |
| 916 var events = this._model.mainThreadEvents(); |
| 917 var filters = this._filters.concat([new WebInspector.TimelineTextFilter(this
._searchRegex)]); |
| 918 var matches = []; |
| 919 for (var index = events.lowerBound(this._windowStartTime, (time, event) => t
ime - event.startTime); |
| 920 index < events.length; ++index) { |
| 921 var event = events[index]; |
| 922 if (event.startTime > this._windowEndTime) |
| 923 break; |
| 924 if (WebInspector.TimelineModel.isVisible(filters, event)) |
| 925 matches.push(event); |
| 926 } |
| 927 |
| 928 var matchesCount = matches.length; |
| 929 if (matchesCount) { |
| 930 this._searchResults = matches; |
| 931 this._searchableView.updateSearchMatchesCount(matchesCount); |
| 932 |
| 933 var selectedIndex = matches.indexOf(this._selectedSearchResult); |
| 934 if (shouldJump && selectedIndex === -1) |
| 935 selectedIndex = jumpBackwards ? this._searchResults.length - 1 : 0; |
| 936 this._selectSearchResult(selectedIndex); |
| 937 } else { |
| 938 this._searchableView.updateSearchMatchesCount(0); |
| 939 delete this._selectedSearchResult; |
| 940 } |
| 941 } |
| 942 |
| 943 /** |
| 944 * @override |
| 945 */ |
| 946 searchCanceled() { |
| 947 this._clearHighlight(); |
| 948 delete this._searchResults; |
| 949 delete this._selectedSearchResult; |
| 950 delete this._searchRegex; |
| 951 } |
| 952 |
| 953 /** |
| 954 * @override |
| 955 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig |
| 956 * @param {boolean} shouldJump |
| 957 * @param {boolean=} jumpBackwards |
| 958 */ |
| 959 performSearch(searchConfig, shouldJump, jumpBackwards) { |
| 960 var query = searchConfig.query; |
| 961 this._searchRegex = createPlainTextSearchRegex(query, 'i'); |
| 962 delete this._searchResults; |
| 963 this._updateSearchHighlight(true, shouldJump, jumpBackwards); |
| 964 } |
| 965 |
| 966 _updateSelectionDetails() { |
| 967 switch (this._selection.type()) { |
| 968 case WebInspector.TimelineSelection.Type.TraceEvent: |
| 969 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._selec
tion.object()); |
| 970 WebInspector.TimelineUIUtils.buildTraceEventDetails( |
| 971 event, this._model, this._detailsLinkifier, true, |
| 972 this._appendDetailsTabsForTraceEventAndShowDetails.bind(this, event)
); |
| 973 break; |
| 974 case WebInspector.TimelineSelection.Type.Frame: |
| 975 var frame = /** @type {!WebInspector.TimelineFrame} */ (this._selection.
object()); |
| 976 var screenshotTime = frame.idle ? |
| 977 frame.startTime : |
| 978 frame.endTime; // For idle frames, look at the state at the beginni
ng of the frame. |
| 979 var filmStripFrame = filmStripFrame = this._filmStripModel.frameByTimest
amp(screenshotTime); |
| 980 if (filmStripFrame && filmStripFrame.timestamp - frame.endTime > 10) |
| 981 filmStripFrame = null; |
| 982 this.showInDetails( |
| 983 WebInspector.TimelineUIUtils.generateDetailsContentForFrame(this._fr
ameModel, frame, filmStripFrame)); |
| 984 if (frame.layerTree) { |
| 985 var layersView = this._layersView(); |
| 986 layersView.showLayerTree(frame.layerTree); |
| 987 if (!this._detailsView.hasTab(WebInspector.TimelinePanel.DetailsTab.La
yerViewer)) |
| 988 this._detailsView.appendTab( |
| 989 WebInspector.TimelinePanel.DetailsTab.LayerViewer, WebInspector.
UIString('Layers'), layersView); |
| 990 } |
| 991 break; |
| 992 case WebInspector.TimelineSelection.Type.NetworkRequest: |
| 993 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest} */
(this._selection.object()); |
| 994 WebInspector.TimelineUIUtils.buildNetworkRequestDetails(request, this._m
odel, this._detailsLinkifier) |
| 995 .then(this.showInDetails.bind(this)); |
| 996 break; |
| 997 case WebInspector.TimelineSelection.Type.Range: |
| 998 this._updateSelectedRangeStats(this._selection._startTime, this._selecti
on._endTime); |
| 999 break; |
| 1000 } |
| 1001 |
| 1002 this._detailsView.updateContents(this._selection); |
| 1003 } |
| 1004 |
| 1005 /** |
| 1006 * @param {!WebInspector.TimelineSelection} selection |
| 1007 * @return {?WebInspector.TimelineFrame} |
| 1008 */ |
| 1009 _frameForSelection(selection) { |
| 1010 switch (selection.type()) { |
| 1011 case WebInspector.TimelineSelection.Type.Frame: |
| 1012 return /** @type {!WebInspector.TimelineFrame} */ (selection.object()); |
| 1013 case WebInspector.TimelineSelection.Type.Range: |
| 1014 return null; |
| 1015 case WebInspector.TimelineSelection.Type.TraceEvent: |
| 1016 return this._frameModel.filteredFrames(selection._endTime, selection._en
dTime)[0]; |
| 1017 default: |
| 1018 console.assert(false, 'Should never be reached'); |
| 1019 return null; |
| 1020 } |
| 1021 } |
| 1022 |
| 1023 /** |
| 1024 * @param {number} offset |
| 1025 */ |
| 1026 _jumpToFrame(offset) { |
| 1027 var currentFrame = this._frameForSelection(this._selection); |
| 1028 if (!currentFrame) |
| 1029 return; |
| 1030 var frames = this._frameModel.frames(); |
| 1031 var index = frames.indexOf(currentFrame); |
| 1032 console.assert(index >= 0, 'Can\'t find current frame in the frame list'); |
| 1033 index = Number.constrain(index + offset, 0, frames.length - 1); |
| 1034 var frame = frames[index]; |
| 1035 this._revealTimeRange(frame.startTime, frame.endTime); |
| 1036 this.select(WebInspector.TimelineSelection.fromFrame(frame)); |
| 1037 return true; |
| 1038 } |
| 1039 |
| 1040 /** |
| 1041 * @param {!WebInspector.PaintProfilerSnapshot} snapshot |
| 1042 */ |
| 1043 _showSnapshotInPaintProfiler(snapshot) { |
| 1044 var paintProfilerView = this._paintProfilerView(); |
| 1045 var hasProfileData = paintProfilerView.setSnapshot(snapshot); |
| 1046 if (!this._detailsView.hasTab(WebInspector.TimelinePanel.DetailsTab.PaintPro
filer)) |
| 1047 this._detailsView.appendTab( |
| 1048 WebInspector.TimelinePanel.DetailsTab.PaintProfiler, WebInspector.UISt
ring('Paint Profiler'), |
| 1049 paintProfilerView, undefined, undefined, true); |
| 1050 this._detailsView.selectTab(WebInspector.TimelinePanel.DetailsTab.PaintProfi
ler, true); |
| 1051 } |
| 1052 |
| 1053 /** |
| 1054 * @param {!WebInspector.TracingModel.Event} event |
| 1055 * @param {!Node} content |
| 1056 */ |
| 1057 _appendDetailsTabsForTraceEventAndShowDetails(event, content) { |
| 1058 this.showInDetails(content); |
| 1059 if (event.name === WebInspector.TimelineModel.RecordType.Paint || |
| 1060 event.name === WebInspector.TimelineModel.RecordType.RasterTask) |
| 1061 this._showEventInPaintProfiler(event); |
| 1062 } |
| 1063 |
| 1064 /** |
| 1065 * @param {!WebInspector.TracingModel.Event} event |
| 1066 */ |
| 1067 _showEventInPaintProfiler(event) { |
| 1068 var target = WebInspector.targetManager.mainTarget(); |
| 1069 if (!target) |
| 1070 return; |
| 1071 var paintProfilerView = this._paintProfilerView(); |
| 1072 var hasProfileData = paintProfilerView.setEvent(target, event); |
| 1073 if (!hasProfileData) |
| 1074 return; |
| 1075 if (!this._detailsView.hasTab(WebInspector.TimelinePanel.DetailsTab.PaintPro
filer)) |
| 1076 this._detailsView.appendTab( |
| 1077 WebInspector.TimelinePanel.DetailsTab.PaintProfiler, WebInspector.UISt
ring('Paint Profiler'), |
| 1078 paintProfilerView, undefined, undefined, false); |
| 1079 } |
| 1080 |
| 1081 /** |
| 1082 * @param {number} startTime |
| 1083 * @param {number} endTime |
| 1084 */ |
| 1085 _updateSelectedRangeStats(startTime, endTime) { |
| 1086 this.showInDetails(WebInspector.TimelineUIUtils.buildRangeStats(this._model,
startTime, endTime)); |
| 1087 } |
| 1088 |
| 1089 /** |
| 1090 * @override |
| 1091 * @param {?WebInspector.TimelineSelection} selection |
| 1092 * @param {!WebInspector.TimelinePanel.DetailsTab=} preferredTab |
| 1093 */ |
| 1094 select(selection, preferredTab) { |
| 1095 if (!selection) |
| 1096 selection = WebInspector.TimelineSelection.fromRange(this._windowStartTime
, this._windowEndTime); |
| 1097 this._selection = selection; |
| 1098 this._detailsLinkifier.reset(); |
| 1099 if (preferredTab) |
| 1100 this._detailsView.setPreferredTab(preferredTab); |
| 1101 |
| 1102 for (var view of this._currentViews) |
| 1103 view.setSelection(selection); |
| 1104 this._updateSelectionDetails(); |
| 1105 } |
| 1106 |
| 1107 /** |
| 1108 * @override |
| 1109 * @param {number} time |
| 1110 */ |
| 1111 selectEntryAtTime(time) { |
| 1112 var events = this._model.mainThreadEvents(); |
| 1113 // Find best match, then backtrack to the first visible entry. |
| 1114 for (var index = events.upperBound(time, (time, event) => time - event.start
Time) - 1; index >= 0; --index) { |
| 1115 var event = events[index]; |
| 1116 var endTime = event.endTime || event.startTime; |
| 1117 if (WebInspector.TracingModel.isTopLevelEvent(event) && endTime < time) |
| 1118 break; |
| 1119 if (WebInspector.TimelineModel.isVisible(this._filters, event) && endTime
>= time) { |
| 1120 this.select(WebInspector.TimelineSelection.fromTraceEvent(event)); |
| 1121 return; |
| 1122 } |
| 1123 } |
| 1124 this.select(null); |
| 1125 } |
| 1126 |
| 1127 /** |
| 1128 * @override |
| 1129 * @param {?WebInspector.TracingModel.Event} event |
| 1130 */ |
| 1131 highlightEvent(event) { |
| 1132 for (var view of this._currentViews) |
| 1133 view.highlightEvent(event); |
| 1134 } |
| 1135 |
| 1136 /** |
| 1137 * @param {number} startTime |
| 1138 * @param {number} endTime |
| 1139 */ |
| 1140 _revealTimeRange(startTime, endTime) { |
| 1141 var timeShift = 0; |
| 1142 if (this._windowEndTime < endTime) |
| 1143 timeShift = endTime - this._windowEndTime; |
| 1144 else if (this._windowStartTime > startTime) |
| 1145 timeShift = startTime - this._windowStartTime; |
| 1146 if (timeShift) |
| 1147 this.requestWindowTimes(this._windowStartTime + timeShift, this._windowEnd
Time + timeShift); |
| 1148 } |
| 1149 |
| 1150 /** |
| 1151 * @override |
| 1152 * @param {!Node} node |
| 1153 */ |
| 1154 showInDetails(node) { |
| 1155 this._detailsView.setContent(node); |
| 1156 } |
| 1157 |
| 1158 /** |
| 1159 * @param {!DataTransfer} dataTransfer |
| 1160 */ |
| 1161 _handleDrop(dataTransfer) { |
| 1162 var items = dataTransfer.items; |
| 1163 if (!items.length) |
| 1164 return; |
| 1165 var item = items[0]; |
| 1166 if (item.kind === 'string') { |
| 1167 var url = dataTransfer.getData('text/uri-list'); |
| 1168 if (new WebInspector.ParsedURL(url).isValid) |
| 1169 this._loadFromURL(url); |
| 1170 } else if (item.kind === 'file') { |
| 1171 var entry = items[0].webkitGetAsEntry(); |
| 1172 if (!entry.isFile) |
| 1173 return; |
| 1174 entry.file(this._loadFromFile.bind(this)); |
| 1175 } |
| 1176 } |
| 1177 |
| 1178 _setAutoWindowTimes() { |
| 1179 var tasks = this._model.mainThreadTasks(); |
| 1180 if (!tasks.length) { |
| 1181 this.requestWindowTimes(this._tracingModel.minimumRecordTime(), this._trac
ingModel.maximumRecordTime()); |
| 1182 return; |
| 1183 } |
| 1184 /** |
| 1185 * @param {number} startIndex |
| 1186 * @param {number} stopIndex |
| 1187 * @return {number} |
| 1188 */ |
| 1189 function findLowUtilizationRegion(startIndex, stopIndex) { |
| 1190 var /** @const */ threshold = 0.1; |
| 1191 var cutIndex = startIndex; |
| 1192 var cutTime = (tasks[cutIndex].startTime() + tasks[cutIndex].endTime()) /
2; |
| 1193 var usedTime = 0; |
| 1194 var step = Math.sign(stopIndex - startIndex); |
| 1195 for (var i = startIndex; i !== stopIndex; i += step) { |
| 1196 var task = tasks[i]; |
| 1197 var taskTime = (task.startTime() + task.endTime()) / 2; |
| 1198 var interval = Math.abs(cutTime - taskTime); |
| 1199 if (usedTime < threshold * interval) { |
| 1200 cutIndex = i; |
| 1201 cutTime = taskTime; |
| 1202 usedTime = 0; |
| 1203 } |
| 1204 usedTime += task.endTime() - task.startTime(); |
| 1205 } |
| 1206 return cutIndex; |
| 1207 } |
| 1208 var rightIndex = findLowUtilizationRegion(tasks.length - 1, 0); |
| 1209 var leftIndex = findLowUtilizationRegion(0, rightIndex); |
| 1210 var leftTime = tasks[leftIndex].startTime(); |
| 1211 var rightTime = tasks[rightIndex].endTime(); |
| 1212 var span = rightTime - leftTime; |
| 1213 var totalSpan = this._tracingModel.maximumRecordTime() - this._tracingModel.
minimumRecordTime(); |
| 1214 if (span < totalSpan * 0.1) { |
| 1215 leftTime = this._tracingModel.minimumRecordTime(); |
| 1216 rightTime = this._tracingModel.maximumRecordTime(); |
| 1217 } else { |
| 1218 leftTime = Math.max(leftTime - 0.05 * span, this._tracingModel.minimumReco
rdTime()); |
| 1219 rightTime = Math.min(rightTime + 0.05 * span, this._tracingModel.maximumRe
cordTime()); |
| 1220 } |
| 1221 this.requestWindowTimes(leftTime, rightTime); |
| 1222 } |
126 }; | 1223 }; |
127 | 1224 |
128 /** | 1225 /** |
129 * @enum {string} | 1226 * @enum {string} |
130 */ | 1227 */ |
131 WebInspector.TimelinePanel.Perspectives = { | 1228 WebInspector.TimelinePanel.Perspectives = { |
132 Load: "Load", | 1229 Load: 'Load', |
133 Responsiveness: "Responsiveness", | 1230 Responsiveness: 'Responsiveness', |
134 Custom: "Custom" | 1231 Custom: 'Custom' |
135 }; | 1232 }; |
136 | 1233 |
137 /** | 1234 /** |
138 * @enum {string} | 1235 * @enum {string} |
139 */ | 1236 */ |
140 WebInspector.TimelinePanel.DetailsTab = { | 1237 WebInspector.TimelinePanel.DetailsTab = { |
141 Details: "Details", | 1238 Details: 'Details', |
142 Events: "Events", | 1239 Events: 'Events', |
143 CallTree: "CallTree", | 1240 CallTree: 'CallTree', |
144 BottomUp: "BottomUp", | 1241 BottomUp: 'BottomUp', |
145 PaintProfiler: "PaintProfiler", | 1242 PaintProfiler: 'PaintProfiler', |
146 LayerViewer: "LayerViewer" | 1243 LayerViewer: 'LayerViewer' |
147 }; | 1244 }; |
148 | 1245 |
149 /** | 1246 /** |
150 * @enum {symbol} | 1247 * @enum {symbol} |
151 */ | 1248 */ |
152 WebInspector.TimelinePanel.State = { | 1249 WebInspector.TimelinePanel.State = { |
153 Idle: Symbol("Idle"), | 1250 Idle: Symbol('Idle'), |
154 StartPending: Symbol("StartPending"), | 1251 StartPending: Symbol('StartPending'), |
155 Recording: Symbol("Recording"), | 1252 Recording: Symbol('Recording'), |
156 StopPending: Symbol("StopPending"), | 1253 StopPending: Symbol('StopPending'), |
157 Loading: Symbol("Loading") | 1254 Loading: Symbol('Loading') |
158 }; | 1255 }; |
159 | 1256 |
160 // Define row and header height, should be in sync with styles for timeline grap
hs. | 1257 // Define row and header height, should be in sync with styles for timeline grap
hs. |
161 WebInspector.TimelinePanel.rowHeight = 18; | 1258 WebInspector.TimelinePanel.rowHeight = 18; |
162 WebInspector.TimelinePanel.headerHeight = 20; | 1259 WebInspector.TimelinePanel.headerHeight = 20; |
163 | 1260 |
164 WebInspector.TimelinePanel.prototype = { | |
165 /** | |
166 * @override | |
167 * @return {?WebInspector.SearchableView} | |
168 */ | |
169 searchableView: function() | |
170 { | |
171 return this._searchableView; | |
172 }, | |
173 | |
174 wasShown: function() | |
175 { | |
176 WebInspector.context.setFlavor(WebInspector.TimelinePanel, this); | |
177 }, | |
178 | |
179 willHide: function() | |
180 { | |
181 WebInspector.context.setFlavor(WebInspector.TimelinePanel, null); | |
182 }, | |
183 | |
184 /** | |
185 * @return {number} | |
186 */ | |
187 windowStartTime: function() | |
188 { | |
189 if (this._windowStartTime) | |
190 return this._windowStartTime; | |
191 return this._model.minimumRecordTime(); | |
192 }, | |
193 | |
194 /** | |
195 * @return {number} | |
196 */ | |
197 windowEndTime: function() | |
198 { | |
199 if (this._windowEndTime < Infinity) | |
200 return this._windowEndTime; | |
201 return this._model.maximumRecordTime() || Infinity; | |
202 }, | |
203 | |
204 /** | |
205 * @param {!WebInspector.Event} event | |
206 */ | |
207 _onWindowChanged: function(event) | |
208 { | |
209 this._windowStartTime = event.data.startTime; | |
210 this._windowEndTime = event.data.endTime; | |
211 | |
212 for (var i = 0; i < this._currentViews.length; ++i) | |
213 this._currentViews[i].setWindowTimes(this._windowStartTime, this._wi
ndowEndTime); | |
214 | |
215 if (!this._selection || this._selection.type() === WebInspector.Timeline
Selection.Type.Range) | |
216 this.select(null); | |
217 }, | |
218 | |
219 /** | |
220 * @param {!WebInspector.Event} event | |
221 */ | |
222 _onOverviewSelectionChanged: function(event) | |
223 { | |
224 var selection = /** @type {!WebInspector.TimelineSelection} */ (event.da
ta); | |
225 this.select(selection); | |
226 }, | |
227 | |
228 /** | |
229 * @override | |
230 * @param {number} windowStartTime | |
231 * @param {number} windowEndTime | |
232 */ | |
233 requestWindowTimes: function(windowStartTime, windowEndTime) | |
234 { | |
235 this._overviewPane.requestWindowTimes(windowStartTime, windowEndTime); | |
236 }, | |
237 | |
238 /** | |
239 * @return {!WebInspector.Widget} | |
240 */ | |
241 _layersView: function() | |
242 { | |
243 if (this._lazyLayersView) | |
244 return this._lazyLayersView; | |
245 this._lazyLayersView = new WebInspector.TimelineLayersView(this._model,
this._showSnapshotInPaintProfiler.bind(this)); | |
246 return this._lazyLayersView; | |
247 }, | |
248 | |
249 _paintProfilerView: function() | |
250 { | |
251 if (this._lazyPaintProfilerView) | |
252 return this._lazyPaintProfilerView; | |
253 this._lazyPaintProfilerView = new WebInspector.TimelinePaintProfilerView
(this._frameModel); | |
254 return this._lazyPaintProfilerView; | |
255 }, | |
256 | |
257 /** | |
258 * @param {!WebInspector.TimelineModeView} modeView | |
259 */ | |
260 _addModeView: function(modeView) | |
261 { | |
262 modeView.setWindowTimes(this.windowStartTime(), this.windowEndTime()); | |
263 modeView.refreshRecords(); | |
264 var splitWidget = this._stackView.appendView(modeView.view(), "timelineP
anelTimelineStackSplitViewState", undefined, 112); | |
265 var resizer = modeView.resizerElement(); | |
266 if (splitWidget && resizer) { | |
267 splitWidget.hideDefaultResizer(); | |
268 splitWidget.installResizer(resizer); | |
269 } | |
270 this._currentViews.push(modeView); | |
271 }, | |
272 | |
273 _removeAllModeViews: function() | |
274 { | |
275 this._currentViews.forEach(view => view.dispose()); | |
276 this._currentViews = []; | |
277 this._stackView.detachChildWidgets(); | |
278 }, | |
279 | |
280 /** | |
281 * @param {!WebInspector.TimelinePanel.State} state | |
282 */ | |
283 _setState: function(state) | |
284 { | |
285 this._state = state; | |
286 this._updateTimelineControls(); | |
287 }, | |
288 | |
289 /** | |
290 * @param {string} name | |
291 * @param {!WebInspector.Setting} setting | |
292 * @param {string} tooltip | |
293 * @return {!WebInspector.ToolbarItem} | |
294 */ | |
295 _createSettingCheckbox: function(name, setting, tooltip) | |
296 { | |
297 if (!this._recordingOptionUIControls) | |
298 this._recordingOptionUIControls = []; | |
299 var checkboxItem = new WebInspector.ToolbarCheckbox(name, tooltip, setti
ng); | |
300 this._recordingOptionUIControls.push(checkboxItem); | |
301 return checkboxItem; | |
302 }, | |
303 | |
304 _createToolbarItems: function() | |
305 { | |
306 this._panelToolbar.removeToolbarItems(); | |
307 | |
308 var perspectiveSetting = WebInspector.settings.createSetting("timelinePe
rspective", WebInspector.TimelinePanel.Perspectives.Load); | |
309 if (Runtime.experiments.isEnabled("timelineRecordingPerspectives")) { | |
310 /** | |
311 * @this {!WebInspector.TimelinePanel} | |
312 */ | |
313 function onPerspectiveChanged() | |
314 { | |
315 perspectiveSetting.set(perspectiveCombobox.selectElement().value
); | |
316 this._createToolbarItems(); | |
317 } | |
318 | |
319 /** | |
320 * @param {string} id | |
321 * @param {string} title | |
322 */ | |
323 function addPerspectiveOption(id, title) | |
324 { | |
325 var option = perspectiveCombobox.createOption(title, "", id); | |
326 perspectiveCombobox.addOption(option); | |
327 if (id === perspectiveSetting.get()) | |
328 perspectiveCombobox.select(option); | |
329 } | |
330 | |
331 var perspectiveCombobox = new WebInspector.ToolbarComboBox(onPerspec
tiveChanged.bind(this)); | |
332 addPerspectiveOption(WebInspector.TimelinePanel.Perspectives.Load, W
ebInspector.UIString("Page Load")); | |
333 addPerspectiveOption(WebInspector.TimelinePanel.Perspectives.Respons
iveness, WebInspector.UIString("Responsiveness")); | |
334 addPerspectiveOption(WebInspector.TimelinePanel.Perspectives.Custom,
WebInspector.UIString("Custom")); | |
335 this._panelToolbar.appendToolbarItem(perspectiveCombobox); | |
336 | |
337 switch (perspectiveSetting.get()) { | |
338 case WebInspector.TimelinePanel.Perspectives.Load: | |
339 this._captureNetworkSetting.set(true); | |
340 this._captureJSProfileSetting.set(true); | |
341 this._captureMemorySetting.set(false); | |
342 this._captureLayersAndPicturesSetting.set(false); | |
343 this._captureFilmStripSetting.set(true); | |
344 break; | |
345 case WebInspector.TimelinePanel.Perspectives.Responsiveness: | |
346 this._captureNetworkSetting.set(true); | |
347 this._captureJSProfileSetting.set(true); | |
348 this._captureMemorySetting.set(false); | |
349 this._captureLayersAndPicturesSetting.set(false); | |
350 this._captureFilmStripSetting.set(false); | |
351 break; | |
352 } | |
353 } | |
354 if (Runtime.experiments.isEnabled("timelineRecordingPerspectives") && pe
rspectiveSetting.get() === WebInspector.TimelinePanel.Perspectives.Load) { | |
355 this._reloadButton = new WebInspector.ToolbarButton(WebInspector.UIS
tring("Record & Reload"), "refresh-toolbar-item"); | |
356 this._reloadButton.addEventListener("click", () => WebInspector.targ
etManager.reloadPage()); | |
357 this._panelToolbar.appendToolbarItem(this._reloadButton); | |
358 } else { | |
359 this._panelToolbar.appendToolbarItem(WebInspector.Toolbar.createActi
onButton(this._toggleRecordAction)); | |
360 } | |
361 | |
362 this._updateTimelineControls(); | |
363 var clearButton = new WebInspector.ToolbarButton(WebInspector.UIString("
Clear recording"), "clear-toolbar-item"); | |
364 clearButton.addEventListener("click", this._clear, this); | |
365 this._panelToolbar.appendToolbarItem(clearButton); | |
366 | |
367 this._panelToolbar.appendSeparator(); | |
368 | |
369 this._panelToolbar.appendText(WebInspector.UIString("Capture:")); | |
370 | |
371 var screenshotCheckbox = this._createSettingCheckbox( | |
372 WebInspector.UIString("Screenshots"), this._captureFilmStripSetting,
WebInspector.UIString("Capture screenshots while recording. (Has small performa
nce overhead)")); | |
373 | |
374 if (!Runtime.experiments.isEnabled("timelineRecordingPerspectives") || p
erspectiveSetting.get() === WebInspector.TimelinePanel.Perspectives.Custom) { | |
375 this._panelToolbar.appendToolbarItem(this._createSettingCheckbox( | |
376 WebInspector.UIString("Network"), this._captureNetworkSetting, W
ebInspector.UIString("Show network requests information"))); | |
377 this._panelToolbar.appendToolbarItem(this._createSettingCheckbox( | |
378 WebInspector.UIString("JS Profile"), this._captureJSProfileSetti
ng, WebInspector.UIString("Capture JavaScript stacks with sampling profiler. (Ha
s small performance overhead)"))); | |
379 this._panelToolbar.appendToolbarItem(screenshotCheckbox); | |
380 this._panelToolbar.appendToolbarItem(this._createSettingCheckbox( | |
381 WebInspector.UIString("Memory"), this._captureMemorySetting, Web
Inspector.UIString("Capture memory information on every timeline event."))); | |
382 this._panelToolbar.appendToolbarItem(this._createSettingCheckbox( | |
383 WebInspector.UIString("Paint"), this._captureLayersAndPicturesSe
tting, WebInspector.UIString("Capture graphics layer positions and rasterization
draw calls. (Has large performance overhead)"))); | |
384 } else { | |
385 this._panelToolbar.appendToolbarItem(screenshotCheckbox); | |
386 } | |
387 | |
388 this._captureNetworkSetting.addChangeListener(this._onNetworkChanged, th
is); | |
389 this._captureMemorySetting.addChangeListener(this._onModeChanged, this); | |
390 this._captureFilmStripSetting.addChangeListener(this._onModeChanged, thi
s); | |
391 | |
392 this._panelToolbar.appendSeparator(); | |
393 var garbageCollectButton = new WebInspector.ToolbarButton(WebInspector.U
IString("Collect garbage"), "garbage-collect-toolbar-item"); | |
394 garbageCollectButton.addEventListener("click", this._garbageCollectButto
nClicked, this); | |
395 this._panelToolbar.appendToolbarItem(garbageCollectButton); | |
396 | |
397 this._panelToolbar.appendSeparator(); | |
398 this._cpuThrottlingCombobox = new WebInspector.ToolbarComboBox(this._onC
PUThrottlingChanged.bind(this)); | |
399 this._panelToolbar.appendToolbarItem(this._cpuThrottlingCombobox); | |
400 this._populateCPUThrottingCombobox(); | |
401 }, | |
402 | |
403 _populateCPUThrottingCombobox: function() | |
404 { | |
405 var cpuThrottlingCombobox = this._cpuThrottlingCombobox; | |
406 cpuThrottlingCombobox.removeOptions(); | |
407 var currentRate = this._cpuThrottlingManager.rate(); | |
408 var hasSelection = false; | |
409 /** | |
410 * @param {string} name | |
411 * @param {number} value | |
412 */ | |
413 function addGroupingOption(name, value) | |
414 { | |
415 var option = cpuThrottlingCombobox.createOption(name, "", String(val
ue)); | |
416 cpuThrottlingCombobox.addOption(option); | |
417 if (hasSelection || (value && value !== currentRate)) | |
418 return; | |
419 cpuThrottlingCombobox.select(option); | |
420 hasSelection = true; | |
421 } | |
422 var predefinedRates = new Map([ | |
423 [1, WebInspector.UIString("No CPU throttling")], | |
424 [2, WebInspector.UIString("High end device (2\xD7 slowdown)")], | |
425 [5, WebInspector.UIString("Low end device (5\xD7 slowdown)")] | |
426 ]); | |
427 for (var rate of predefinedRates) | |
428 addGroupingOption(rate[1], rate[0]); | |
429 if (this._customCPUThrottlingRate && !predefinedRates.has(this._customCP
UThrottlingRate)) | |
430 addGroupingOption(WebInspector.UIString("Custom rate (%d\xD7 slowdow
n)", this._customCPUThrottlingRate), this._customCPUThrottlingRate); | |
431 addGroupingOption(WebInspector.UIString("Set custom rate\u2026"), 0); | |
432 }, | |
433 | |
434 _prepareToLoadTimeline: function() | |
435 { | |
436 console.assert(this._state === WebInspector.TimelinePanel.State.Idle); | |
437 this._setState(WebInspector.TimelinePanel.State.Loading); | |
438 }, | |
439 | |
440 _createFileSelector: function() | |
441 { | |
442 if (this._fileSelectorElement) | |
443 this._fileSelectorElement.remove(); | |
444 this._fileSelectorElement = WebInspector.createFileSelectorElement(this.
_loadFromFile.bind(this)); | |
445 this.element.appendChild(this._fileSelectorElement); | |
446 }, | |
447 | |
448 /** | |
449 * @param {!Event} event | |
450 */ | |
451 _contextMenu: function(event) | |
452 { | |
453 var contextMenu = new WebInspector.ContextMenu(event); | |
454 contextMenu.appendItemsAtLocation("timelineMenu"); | |
455 contextMenu.show(); | |
456 }, | |
457 | |
458 /** | |
459 * @return {boolean} | |
460 */ | |
461 _saveToFile: function() | |
462 { | |
463 if (this._state !== WebInspector.TimelinePanel.State.Idle) | |
464 return true; | |
465 if (this._model.isEmpty()) | |
466 return true; | |
467 | |
468 var now = new Date(); | |
469 var fileName = "TimelineRawData-" + now.toISO8601Compact() + ".json"; | |
470 var stream = new WebInspector.FileOutputStream(); | |
471 | |
472 /** | |
473 * @param {boolean} accepted | |
474 * @this {WebInspector.TimelinePanel} | |
475 */ | |
476 function callback(accepted) | |
477 { | |
478 if (!accepted) | |
479 return; | |
480 var saver = new WebInspector.TracingTimelineSaver(); | |
481 this._tracingModelBackingStorage.writeToStream(stream, saver); | |
482 } | |
483 stream.open(fileName, callback.bind(this)); | |
484 return true; | |
485 }, | |
486 | |
487 /** | |
488 * @return {boolean} | |
489 */ | |
490 _selectFileToLoad: function() | |
491 { | |
492 this._fileSelectorElement.click(); | |
493 return true; | |
494 }, | |
495 | |
496 /** | |
497 * @param {!File} file | |
498 */ | |
499 _loadFromFile: function(file) | |
500 { | |
501 if (this._state !== WebInspector.TimelinePanel.State.Idle) | |
502 return; | |
503 this._prepareToLoadTimeline(); | |
504 this._loader = WebInspector.TimelineLoader.loadFromFile(this._tracingMod
el, file, this); | |
505 this._createFileSelector(); | |
506 }, | |
507 | |
508 /** | |
509 * @param {string} url | |
510 */ | |
511 _loadFromURL: function(url) | |
512 { | |
513 if (this._state !== WebInspector.TimelinePanel.State.Idle) | |
514 return; | |
515 this._prepareToLoadTimeline(); | |
516 this._loader = WebInspector.TimelineLoader.loadFromURL(this._tracingMode
l, url, this); | |
517 }, | |
518 | |
519 _refreshViews: function() | |
520 { | |
521 for (var i = 0; i < this._currentViews.length; ++i) { | |
522 var view = this._currentViews[i]; | |
523 view.refreshRecords(); | |
524 } | |
525 this._updateSelectionDetails(); | |
526 }, | |
527 | |
528 _onModeChanged: function() | |
529 { | |
530 // Set up overview controls. | |
531 this._overviewControls = []; | |
532 this._overviewControls.push(new WebInspector.TimelineEventOverview.Respo
nsiveness(this._model, this._frameModel)); | |
533 if (Runtime.experiments.isEnabled("inputEventsOnTimelineOverview")) | |
534 this._overviewControls.push(new WebInspector.TimelineEventOverview.I
nput(this._model)); | |
535 this._overviewControls.push(new WebInspector.TimelineEventOverview.Frame
s(this._model, this._frameModel)); | |
536 this._overviewControls.push(new WebInspector.TimelineEventOverview.CPUAc
tivity(this._model)); | |
537 this._overviewControls.push(new WebInspector.TimelineEventOverview.Netwo
rk(this._model)); | |
538 if (this._captureFilmStripSetting.get()) | |
539 this._overviewControls.push(new WebInspector.TimelineFilmStripOvervi
ew(this._model, this._filmStripModel)); | |
540 if (this._captureMemorySetting.get()) | |
541 this._overviewControls.push(new WebInspector.TimelineEventOverview.M
emory(this._model)); | |
542 this._overviewPane.setOverviewControls(this._overviewControls); | |
543 | |
544 // Set up the main view. | |
545 this._removeAllModeViews(); | |
546 this._flameChart = new WebInspector.TimelineFlameChartView(this, this._m
odel, this._frameModel, this._irModel, this._filters); | |
547 this._flameChart.enableNetworkPane(this._captureNetworkSetting.get()); | |
548 this._addModeView(this._flameChart); | |
549 | |
550 if (this._captureMemorySetting.get()) | |
551 this._addModeView(new WebInspector.MemoryCountersGraph(this, this._m
odel, [WebInspector.TimelineUIUtils.visibleEventsFilter()])); | |
552 | |
553 this.doResize(); | |
554 this.select(null); | |
555 }, | |
556 | |
557 _onNetworkChanged: function() | |
558 { | |
559 if (this._flameChart) | |
560 this._flameChart.enableNetworkPane(this._captureNetworkSetting.get()
, true); | |
561 }, | |
562 | |
563 _onCPUThrottlingChanged: function() | |
564 { | |
565 if (!this._cpuThrottlingManager) | |
566 return; | |
567 var value = this._cpuThrottlingCombobox.selectedOption().value; | |
568 var isLastOption = this._cpuThrottlingCombobox.selectedIndex() === this.
_cpuThrottlingCombobox.size() - 1; | |
569 this._populateCPUThrottingCombobox(); | |
570 var resultPromise = isLastOption | |
571 ? WebInspector.TimelinePanel.CustomCPUThrottlingRateDialog.show(this
._cpuThrottlingCombobox.element) | |
572 : Promise.resolve(value); | |
573 resultPromise.then(text => { | |
574 var value = Number.parseFloat(text); | |
575 if (value >= 1) { | |
576 if (isLastOption) | |
577 this._customCPUThrottlingRate = value; | |
578 this._cpuThrottlingManager.setRate(value); | |
579 this._populateCPUThrottingCombobox(); | |
580 } | |
581 }); | |
582 }, | |
583 | |
584 /** | |
585 * @param {boolean} enabled | |
586 */ | |
587 _setUIControlsEnabled: function(enabled) | |
588 { | |
589 /** | |
590 * @param {!WebInspector.ToolbarButton} toolbarButton | |
591 */ | |
592 function handler(toolbarButton) | |
593 { | |
594 toolbarButton.setEnabled(enabled); | |
595 } | |
596 this._recordingOptionUIControls.forEach(handler); | |
597 }, | |
598 | |
599 /** | |
600 * @param {boolean} userInitiated | |
601 */ | |
602 _startRecording: function(userInitiated) | |
603 { | |
604 console.assert(!this._statusPane, "Status pane is already opened."); | |
605 var mainTarget = WebInspector.targetManager.mainTarget(); | |
606 if (!mainTarget) | |
607 return; | |
608 this._setState(WebInspector.TimelinePanel.State.StartPending); | |
609 this._showRecordingStarted(); | |
610 | |
611 this._autoRecordGeneration = userInitiated ? null : Symbol("Generation")
; | |
612 this._controller = new WebInspector.TimelineController(mainTarget, this,
this._tracingModel); | |
613 this._controller.startRecording(true, this._captureJSProfileSetting.get(
), this._captureMemorySetting.get(), this._captureLayersAndPicturesSetting.get()
, this._captureFilmStripSetting && this._captureFilmStripSetting.get()); | |
614 | |
615 for (var i = 0; i < this._overviewControls.length; ++i) | |
616 this._overviewControls[i].timelineStarted(); | |
617 | |
618 if (userInitiated) | |
619 WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action
.TimelineStarted); | |
620 this._setUIControlsEnabled(false); | |
621 this._hideRecordingHelpMessage(); | |
622 }, | |
623 | |
624 _stopRecording: function() | |
625 { | |
626 if (this._statusPane) { | |
627 this._statusPane.finish(); | |
628 this._statusPane.updateStatus(WebInspector.UIString("Stopping timeli
ne\u2026")); | |
629 this._statusPane.updateProgressBar(WebInspector.UIString("Received")
, 0); | |
630 } | |
631 this._setState(WebInspector.TimelinePanel.State.StopPending); | |
632 this._autoRecordGeneration = null; | |
633 this._controller.stopRecording(); | |
634 this._controller = null; | |
635 this._setUIControlsEnabled(true); | |
636 }, | |
637 | |
638 _onSuspendStateChanged: function() | |
639 { | |
640 this._updateTimelineControls(); | |
641 }, | |
642 | |
643 _updateTimelineControls: function() | |
644 { | |
645 var state = WebInspector.TimelinePanel.State; | |
646 this._toggleRecordAction.setToggled(this._state === state.Recording); | |
647 this._toggleRecordAction.setEnabled(this._state === state.Recording || t
his._state === state.Idle); | |
648 this._panelToolbar.setEnabled(this._state !== state.Loading); | |
649 this._dropTarget.setEnabled(this._state === state.Idle); | |
650 }, | |
651 | |
652 _toggleRecording: function() | |
653 { | |
654 if (this._state === WebInspector.TimelinePanel.State.Idle) | |
655 this._startRecording(true); | |
656 else if (this._state === WebInspector.TimelinePanel.State.Recording) | |
657 this._stopRecording(); | |
658 }, | |
659 | |
660 _garbageCollectButtonClicked: function() | |
661 { | |
662 var targets = WebInspector.targetManager.targets(); | |
663 for (var i = 0; i < targets.length; ++i) | |
664 targets[i].heapProfilerAgent().collectGarbage(); | |
665 }, | |
666 | |
667 _clear: function() | |
668 { | |
669 WebInspector.LineLevelProfile.instance().reset(); | |
670 this._tracingModel.reset(); | |
671 this._model.reset(); | |
672 this._showRecordingHelpMessage(); | |
673 | |
674 this.requestWindowTimes(0, Infinity); | |
675 delete this._selection; | |
676 this._frameModel.reset(); | |
677 this._filmStripModel.reset(this._tracingModel); | |
678 this._overviewPane.reset(); | |
679 for (var i = 0; i < this._currentViews.length; ++i) | |
680 this._currentViews[i].reset(); | |
681 for (var i = 0; i < this._overviewControls.length; ++i) | |
682 this._overviewControls[i].reset(); | |
683 this.select(null); | |
684 this._detailsSplitWidget.hideSidebar(); | |
685 }, | |
686 | |
687 /** | |
688 * @override | |
689 */ | |
690 recordingStarted: function() | |
691 { | |
692 this._clear(); | |
693 this._setState(WebInspector.TimelinePanel.State.Recording); | |
694 this._showRecordingStarted(); | |
695 this._statusPane.updateStatus(WebInspector.UIString("Recording\u2026")); | |
696 this._statusPane.updateProgressBar(WebInspector.UIString("Buffer usage")
, 0); | |
697 this._statusPane.startTimer(); | |
698 this._hideRecordingHelpMessage(); | |
699 }, | |
700 | |
701 /** | |
702 * @override | |
703 * @param {number} usage | |
704 */ | |
705 recordingProgress: function(usage) | |
706 { | |
707 this._statusPane.updateProgressBar(WebInspector.UIString("Buffer usage")
, usage * 100); | |
708 }, | |
709 | |
710 _showRecordingHelpMessage: function() | |
711 { | |
712 /** | |
713 * @param {string} tagName | |
714 * @param {string} contents | |
715 * @return {!Element} | |
716 */ | |
717 function encloseWithTag(tagName, contents) | |
718 { | |
719 var e = createElement(tagName); | |
720 e.textContent = contents; | |
721 return e; | |
722 } | |
723 | |
724 var recordNode = encloseWithTag("b", WebInspector.shortcutRegistry.short
cutDescriptorsForAction("timeline.toggle-recording")[0].name); | |
725 var reloadNode = encloseWithTag("b", WebInspector.shortcutRegistry.short
cutDescriptorsForAction("main.reload")[0].name); | |
726 var navigateNode = encloseWithTag("b", WebInspector.UIString("WASD (ZQSD
)")); | |
727 var hintText = createElementWithClass("div"); | |
728 hintText.appendChild(WebInspector.formatLocalized("To capture a new time
line, click the record toolbar button or hit %s.", [recordNode])); | |
729 hintText.createChild("br"); | |
730 hintText.appendChild(WebInspector.formatLocalized("To evaluate page load
performance, hit %s to record the reload.", [reloadNode])); | |
731 hintText.createChild("p"); | |
732 hintText.appendChild(WebInspector.formatLocalized("After recording, sele
ct an area of interest in the overview by dragging.", [])); | |
733 hintText.createChild("br"); | |
734 hintText.appendChild(WebInspector.formatLocalized("Then, zoom and pan th
e timeline with the mousewheel and %s keys.", [navigateNode])); | |
735 this._hideRecordingHelpMessage(); | |
736 this._helpMessageElement = this._searchableView.element.createChild("div
", "full-widget-dimmed-banner timeline-status-pane"); | |
737 this._helpMessageElement.appendChild(hintText); | |
738 }, | |
739 | |
740 _hideRecordingHelpMessage: function() | |
741 { | |
742 if (this._helpMessageElement) | |
743 this._helpMessageElement.remove(); | |
744 delete this._helpMessageElement; | |
745 }, | |
746 | |
747 /** | |
748 * @override | |
749 */ | |
750 loadingStarted: function() | |
751 { | |
752 this._hideRecordingHelpMessage(); | |
753 | |
754 if (this._statusPane) | |
755 this._statusPane.hide(); | |
756 this._statusPane = new WebInspector.TimelinePanel.StatusPane(false, this
._cancelLoading.bind(this)); | |
757 this._statusPane.showPane(this._statusPaneContainer); | |
758 this._statusPane.updateStatus(WebInspector.UIString("Loading timeline\u2
026")); | |
759 // FIXME: make loading from backend cancelable as well. | |
760 if (!this._loader) | |
761 this._statusPane.finish(); | |
762 this.loadingProgress(0); | |
763 }, | |
764 | |
765 /** | |
766 * @override | |
767 * @param {number=} progress | |
768 */ | |
769 loadingProgress: function(progress) | |
770 { | |
771 if (typeof progress === "number") | |
772 this._statusPane.updateProgressBar(WebInspector.UIString("Received")
, progress * 100); | |
773 }, | |
774 | |
775 /** | |
776 * @override | |
777 * @param {boolean} success | |
778 */ | |
779 loadingComplete: function(success) | |
780 { | |
781 var loadedFromFile = !!this._loader; | |
782 delete this._loader; | |
783 this._setState(WebInspector.TimelinePanel.State.Idle); | |
784 | |
785 if (!success) { | |
786 this._statusPane.hide(); | |
787 delete this._statusPane; | |
788 this._clear(); | |
789 return; | |
790 } | |
791 | |
792 if (this._statusPane) | |
793 this._statusPane.updateStatus(WebInspector.UIString("Processing time
line\u2026")); | |
794 this._model.setEvents(this._tracingModel, loadedFromFile); | |
795 this._frameModel.reset(); | |
796 this._frameModel.addTraceEvents(WebInspector.targetManager.mainTarget(),
this._model.inspectedTargetEvents(), this._model.sessionId() || ""); | |
797 this._filmStripModel.reset(this._tracingModel); | |
798 var groups = WebInspector.TimelineModel.AsyncEventGroup; | |
799 var asyncEventsByGroup = this._model.mainThreadAsyncEvents(); | |
800 this._irModel.populate(asyncEventsByGroup.get(groups.input), asyncEvents
ByGroup.get(groups.animation)); | |
801 this._model.cpuProfiles().forEach(profile => WebInspector.LineLevelProfi
le.instance().appendCPUProfile(profile)); | |
802 if (this._statusPane) | |
803 this._statusPane.hide(); | |
804 delete this._statusPane; | |
805 this._overviewPane.reset(); | |
806 this._overviewPane.setBounds(this._model.minimumRecordTime(), this._mode
l.maximumRecordTime()); | |
807 this._setAutoWindowTimes(); | |
808 this._refreshViews(); | |
809 for (var i = 0; i < this._overviewControls.length; ++i) | |
810 this._overviewControls[i].timelineStopped(); | |
811 this._setMarkers(); | |
812 this._overviewPane.scheduleUpdate(); | |
813 this._updateSearchHighlight(false, true); | |
814 this._detailsSplitWidget.showBoth(); | |
815 }, | |
816 | |
817 _showRecordingStarted: function() | |
818 { | |
819 if (this._statusPane) | |
820 return; | |
821 this._statusPane = new WebInspector.TimelinePanel.StatusPane(true, this.
_stopRecording.bind(this)); | |
822 this._statusPane.showPane(this._statusPaneContainer); | |
823 this._statusPane.updateStatus(WebInspector.UIString("Initializing record
ing\u2026")); | |
824 }, | |
825 | |
826 _cancelLoading: function() | |
827 { | |
828 if (this._loader) | |
829 this._loader.cancel(); | |
830 }, | |
831 | |
832 _setMarkers: function() | |
833 { | |
834 var markers = new Map(); | |
835 var recordTypes = WebInspector.TimelineModel.RecordType; | |
836 var zeroTime = this._model.minimumRecordTime(); | |
837 for (var record of this._model.eventDividerRecords()) { | |
838 if (record.type() === recordTypes.TimeStamp || record.type() === rec
ordTypes.ConsoleTime) | |
839 continue; | |
840 markers.set(record.startTime(), WebInspector.TimelineUIUtils.createD
ividerForRecord(record, zeroTime, 0)); | |
841 } | |
842 this._overviewPane.setMarkers(markers); | |
843 }, | |
844 | |
845 /** | |
846 * @param {!WebInspector.Event} event | |
847 */ | |
848 _pageReloadRequested: function(event) | |
849 { | |
850 if (this._state !== WebInspector.TimelinePanel.State.Idle || !this.isSho
wing()) | |
851 return; | |
852 this._startRecording(false); | |
853 }, | |
854 | |
855 /** | |
856 * @param {!WebInspector.Event} event | |
857 */ | |
858 _loadEventFired: function(event) | |
859 { | |
860 if (this._state !== WebInspector.TimelinePanel.State.Recording || !this.
_autoRecordGeneration) | |
861 return; | |
862 setTimeout(stopRecordingOnReload.bind(this, this._autoRecordGeneration),
this._millisecondsToRecordAfterLoadEvent); | |
863 | |
864 /** | |
865 * @this {WebInspector.TimelinePanel} | |
866 * @param {!Object} recordGeneration | |
867 */ | |
868 function stopRecordingOnReload(recordGeneration) | |
869 { | |
870 // Check if we're still in the same recording session. | |
871 if (this._state !== WebInspector.TimelinePanel.State.Recording || th
is._autoRecordGeneration !== recordGeneration) | |
872 return; | |
873 this._stopRecording(); | |
874 } | |
875 }, | |
876 | |
877 // WebInspector.Searchable implementation | |
878 | |
879 /** | |
880 * @override | |
881 */ | |
882 jumpToNextSearchResult: function() | |
883 { | |
884 if (!this._searchResults || !this._searchResults.length) | |
885 return; | |
886 var index = this._selectedSearchResult ? this._searchResults.indexOf(thi
s._selectedSearchResult) : -1; | |
887 this._jumpToSearchResult(index + 1); | |
888 }, | |
889 | |
890 /** | |
891 * @override | |
892 */ | |
893 jumpToPreviousSearchResult: function() | |
894 { | |
895 if (!this._searchResults || !this._searchResults.length) | |
896 return; | |
897 var index = this._selectedSearchResult ? this._searchResults.indexOf(thi
s._selectedSearchResult) : 0; | |
898 this._jumpToSearchResult(index - 1); | |
899 }, | |
900 | |
901 /** | |
902 * @override | |
903 * @return {boolean} | |
904 */ | |
905 supportsCaseSensitiveSearch: function() | |
906 { | |
907 return false; | |
908 }, | |
909 | |
910 /** | |
911 * @override | |
912 * @return {boolean} | |
913 */ | |
914 supportsRegexSearch: function() | |
915 { | |
916 return false; | |
917 }, | |
918 | |
919 /** | |
920 * @param {number} index | |
921 */ | |
922 _jumpToSearchResult: function(index) | |
923 { | |
924 this._selectSearchResult((index + this._searchResults.length) % this._se
archResults.length); | |
925 this._currentViews[0].highlightSearchResult(this._selectedSearchResult,
this._searchRegex, true); | |
926 }, | |
927 | |
928 /** | |
929 * @param {number} index | |
930 */ | |
931 _selectSearchResult: function(index) | |
932 { | |
933 this._selectedSearchResult = this._searchResults[index]; | |
934 this._searchableView.updateCurrentMatchIndex(index); | |
935 }, | |
936 | |
937 _clearHighlight: function() | |
938 { | |
939 this._currentViews[0].highlightSearchResult(null); | |
940 }, | |
941 | |
942 /** | |
943 * @param {boolean} revealRecord | |
944 * @param {boolean} shouldJump | |
945 * @param {boolean=} jumpBackwards | |
946 */ | |
947 _updateSearchHighlight: function(revealRecord, shouldJump, jumpBackwards) | |
948 { | |
949 if (!this._searchRegex) { | |
950 this._clearHighlight(); | |
951 return; | |
952 } | |
953 | |
954 if (!this._searchResults) | |
955 this._updateSearchResults(shouldJump, jumpBackwards); | |
956 this._currentViews[0].highlightSearchResult(this._selectedSearchResult,
this._searchRegex, revealRecord); | |
957 }, | |
958 | |
959 /** | |
960 * @param {boolean} shouldJump | |
961 * @param {boolean=} jumpBackwards | |
962 */ | |
963 _updateSearchResults: function(shouldJump, jumpBackwards) | |
964 { | |
965 if (!this._searchRegex) | |
966 return; | |
967 | |
968 // FIXME: search on all threads. | |
969 var events = this._model.mainThreadEvents(); | |
970 var filters = this._filters.concat([new WebInspector.TimelineTextFilter(
this._searchRegex)]); | |
971 var matches = []; | |
972 for (var index = events.lowerBound(this._windowStartTime, (time, event)
=> time - event.startTime); index < events.length; ++index) { | |
973 var event = events[index]; | |
974 if (event.startTime > this._windowEndTime) | |
975 break; | |
976 if (WebInspector.TimelineModel.isVisible(filters, event)) | |
977 matches.push(event); | |
978 } | |
979 | |
980 var matchesCount = matches.length; | |
981 if (matchesCount) { | |
982 this._searchResults = matches; | |
983 this._searchableView.updateSearchMatchesCount(matchesCount); | |
984 | |
985 var selectedIndex = matches.indexOf(this._selectedSearchResult); | |
986 if (shouldJump && selectedIndex === -1) | |
987 selectedIndex = jumpBackwards ? this._searchResults.length - 1 :
0; | |
988 this._selectSearchResult(selectedIndex); | |
989 } else { | |
990 this._searchableView.updateSearchMatchesCount(0); | |
991 delete this._selectedSearchResult; | |
992 } | |
993 }, | |
994 | |
995 /** | |
996 * @override | |
997 */ | |
998 searchCanceled: function() | |
999 { | |
1000 this._clearHighlight(); | |
1001 delete this._searchResults; | |
1002 delete this._selectedSearchResult; | |
1003 delete this._searchRegex; | |
1004 }, | |
1005 | |
1006 /** | |
1007 * @override | |
1008 * @param {!WebInspector.SearchableView.SearchConfig} searchConfig | |
1009 * @param {boolean} shouldJump | |
1010 * @param {boolean=} jumpBackwards | |
1011 */ | |
1012 performSearch: function(searchConfig, shouldJump, jumpBackwards) | |
1013 { | |
1014 var query = searchConfig.query; | |
1015 this._searchRegex = createPlainTextSearchRegex(query, "i"); | |
1016 delete this._searchResults; | |
1017 this._updateSearchHighlight(true, shouldJump, jumpBackwards); | |
1018 }, | |
1019 | |
1020 _updateSelectionDetails: function() | |
1021 { | |
1022 switch (this._selection.type()) { | |
1023 case WebInspector.TimelineSelection.Type.TraceEvent: | |
1024 var event = /** @type {!WebInspector.TracingModel.Event} */ (this._s
election.object()); | |
1025 WebInspector.TimelineUIUtils.buildTraceEventDetails(event, this._mod
el, this._detailsLinkifier, true, this._appendDetailsTabsForTraceEventAndShowDet
ails.bind(this, event)); | |
1026 break; | |
1027 case WebInspector.TimelineSelection.Type.Frame: | |
1028 var frame = /** @type {!WebInspector.TimelineFrame} */ (this._select
ion.object()); | |
1029 var screenshotTime = frame.idle ? frame.startTime : frame.endTime; /
/ For idle frames, look at the state at the beginning of the frame. | |
1030 var filmStripFrame = filmStripFrame = this._filmStripModel.frameByTi
mestamp(screenshotTime); | |
1031 if (filmStripFrame && filmStripFrame.timestamp - frame.endTime > 10) | |
1032 filmStripFrame = null; | |
1033 this.showInDetails(WebInspector.TimelineUIUtils.generateDetailsConte
ntForFrame(this._frameModel, frame, filmStripFrame)); | |
1034 if (frame.layerTree) { | |
1035 var layersView = this._layersView(); | |
1036 layersView.showLayerTree(frame.layerTree); | |
1037 if (!this._detailsView.hasTab(WebInspector.TimelinePanel.Details
Tab.LayerViewer)) | |
1038 this._detailsView.appendTab(WebInspector.TimelinePanel.Detai
lsTab.LayerViewer, WebInspector.UIString("Layers"), layersView); | |
1039 } | |
1040 break; | |
1041 case WebInspector.TimelineSelection.Type.NetworkRequest: | |
1042 var request = /** @type {!WebInspector.TimelineModel.NetworkRequest}
*/ (this._selection.object()); | |
1043 WebInspector.TimelineUIUtils.buildNetworkRequestDetails(request, thi
s._model, this._detailsLinkifier) | |
1044 .then(this.showInDetails.bind(this)); | |
1045 break; | |
1046 case WebInspector.TimelineSelection.Type.Range: | |
1047 this._updateSelectedRangeStats(this._selection._startTime, this._sel
ection._endTime); | |
1048 break; | |
1049 } | |
1050 | |
1051 this._detailsView.updateContents(this._selection); | |
1052 }, | |
1053 | |
1054 /** | |
1055 * @param {!WebInspector.TimelineSelection} selection | |
1056 * @return {?WebInspector.TimelineFrame} | |
1057 */ | |
1058 _frameForSelection: function(selection) | |
1059 { | |
1060 switch (selection.type()) { | |
1061 case WebInspector.TimelineSelection.Type.Frame: | |
1062 return /** @type {!WebInspector.TimelineFrame} */ (selection.object(
)); | |
1063 case WebInspector.TimelineSelection.Type.Range: | |
1064 return null; | |
1065 case WebInspector.TimelineSelection.Type.TraceEvent: | |
1066 return this._frameModel.filteredFrames(selection._endTime, selection
._endTime)[0]; | |
1067 default: | |
1068 console.assert(false, "Should never be reached"); | |
1069 return null; | |
1070 } | |
1071 }, | |
1072 | |
1073 /** | |
1074 * @param {number} offset | |
1075 */ | |
1076 _jumpToFrame: function(offset) | |
1077 { | |
1078 var currentFrame = this._frameForSelection(this._selection); | |
1079 if (!currentFrame) | |
1080 return; | |
1081 var frames = this._frameModel.frames(); | |
1082 var index = frames.indexOf(currentFrame); | |
1083 console.assert(index >= 0, "Can't find current frame in the frame list")
; | |
1084 index = Number.constrain(index + offset, 0, frames.length - 1); | |
1085 var frame = frames[index]; | |
1086 this._revealTimeRange(frame.startTime, frame.endTime); | |
1087 this.select(WebInspector.TimelineSelection.fromFrame(frame)); | |
1088 return true; | |
1089 }, | |
1090 | |
1091 /** | |
1092 * @param {!WebInspector.PaintProfilerSnapshot} snapshot | |
1093 */ | |
1094 _showSnapshotInPaintProfiler: function(snapshot) | |
1095 { | |
1096 var paintProfilerView = this._paintProfilerView(); | |
1097 var hasProfileData = paintProfilerView.setSnapshot(snapshot); | |
1098 if (!this._detailsView.hasTab(WebInspector.TimelinePanel.DetailsTab.Pain
tProfiler)) | |
1099 this._detailsView.appendTab(WebInspector.TimelinePanel.DetailsTab.Pa
intProfiler, WebInspector.UIString("Paint Profiler"), paintProfilerView, undefin
ed, undefined, true); | |
1100 this._detailsView.selectTab(WebInspector.TimelinePanel.DetailsTab.PaintP
rofiler, true); | |
1101 }, | |
1102 | |
1103 /** | |
1104 * @param {!WebInspector.TracingModel.Event} event | |
1105 * @param {!Node} content | |
1106 */ | |
1107 _appendDetailsTabsForTraceEventAndShowDetails: function(event, content) | |
1108 { | |
1109 this.showInDetails(content); | |
1110 if (event.name === WebInspector.TimelineModel.RecordType.Paint || event.
name === WebInspector.TimelineModel.RecordType.RasterTask) | |
1111 this._showEventInPaintProfiler(event); | |
1112 }, | |
1113 | |
1114 /** | |
1115 * @param {!WebInspector.TracingModel.Event} event | |
1116 */ | |
1117 _showEventInPaintProfiler: function(event) | |
1118 { | |
1119 var target = WebInspector.targetManager.mainTarget(); | |
1120 if (!target) | |
1121 return; | |
1122 var paintProfilerView = this._paintProfilerView(); | |
1123 var hasProfileData = paintProfilerView.setEvent(target, event); | |
1124 if (!hasProfileData) | |
1125 return; | |
1126 if (!this._detailsView.hasTab(WebInspector.TimelinePanel.DetailsTab.Pain
tProfiler)) | |
1127 this._detailsView.appendTab(WebInspector.TimelinePanel.DetailsTab.Pa
intProfiler, WebInspector.UIString("Paint Profiler"), paintProfilerView, undefin
ed, undefined, false); | |
1128 }, | |
1129 | |
1130 /** | |
1131 * @param {number} startTime | |
1132 * @param {number} endTime | |
1133 */ | |
1134 _updateSelectedRangeStats: function(startTime, endTime) | |
1135 { | |
1136 this.showInDetails(WebInspector.TimelineUIUtils.buildRangeStats(this._mo
del, startTime, endTime)); | |
1137 }, | |
1138 | |
1139 /** | |
1140 * @override | |
1141 * @param {?WebInspector.TimelineSelection} selection | |
1142 * @param {!WebInspector.TimelinePanel.DetailsTab=} preferredTab | |
1143 */ | |
1144 select: function(selection, preferredTab) | |
1145 { | |
1146 if (!selection) | |
1147 selection = WebInspector.TimelineSelection.fromRange(this._windowSta
rtTime, this._windowEndTime); | |
1148 this._selection = selection; | |
1149 this._detailsLinkifier.reset(); | |
1150 if (preferredTab) | |
1151 this._detailsView.setPreferredTab(preferredTab); | |
1152 | |
1153 for (var view of this._currentViews) | |
1154 view.setSelection(selection); | |
1155 this._updateSelectionDetails(); | |
1156 }, | |
1157 | |
1158 /** | |
1159 * @override | |
1160 * @param {number} time | |
1161 */ | |
1162 selectEntryAtTime: function(time) | |
1163 { | |
1164 var events = this._model.mainThreadEvents(); | |
1165 // Find best match, then backtrack to the first visible entry. | |
1166 for (var index = events.upperBound(time, (time, event) => time - event.s
tartTime) - 1; index >= 0; --index) { | |
1167 var event = events[index]; | |
1168 var endTime = event.endTime || event.startTime; | |
1169 if (WebInspector.TracingModel.isTopLevelEvent(event) && endTime < ti
me) | |
1170 break; | |
1171 if (WebInspector.TimelineModel.isVisible(this._filters, event) && en
dTime >= time) { | |
1172 this.select(WebInspector.TimelineSelection.fromTraceEvent(event)
); | |
1173 return; | |
1174 } | |
1175 } | |
1176 this.select(null); | |
1177 }, | |
1178 | |
1179 /** | |
1180 * @override | |
1181 * @param {?WebInspector.TracingModel.Event} event | |
1182 */ | |
1183 highlightEvent: function(event) | |
1184 { | |
1185 for (var view of this._currentViews) | |
1186 view.highlightEvent(event); | |
1187 }, | |
1188 | |
1189 /** | |
1190 * @param {number} startTime | |
1191 * @param {number} endTime | |
1192 */ | |
1193 _revealTimeRange: function(startTime, endTime) | |
1194 { | |
1195 var timeShift = 0; | |
1196 if (this._windowEndTime < endTime) | |
1197 timeShift = endTime - this._windowEndTime; | |
1198 else if (this._windowStartTime > startTime) | |
1199 timeShift = startTime - this._windowStartTime; | |
1200 if (timeShift) | |
1201 this.requestWindowTimes(this._windowStartTime + timeShift, this._win
dowEndTime + timeShift); | |
1202 }, | |
1203 | |
1204 /** | |
1205 * @override | |
1206 * @param {!Node} node | |
1207 */ | |
1208 showInDetails: function(node) | |
1209 { | |
1210 this._detailsView.setContent(node); | |
1211 }, | |
1212 | |
1213 /** | |
1214 * @param {!DataTransfer} dataTransfer | |
1215 */ | |
1216 _handleDrop: function(dataTransfer) | |
1217 { | |
1218 var items = dataTransfer.items; | |
1219 if (!items.length) | |
1220 return; | |
1221 var item = items[0]; | |
1222 if (item.kind === "string") { | |
1223 var url = dataTransfer.getData("text/uri-list"); | |
1224 if (new WebInspector.ParsedURL(url).isValid) | |
1225 this._loadFromURL(url); | |
1226 } else if (item.kind === "file") { | |
1227 var entry = items[0].webkitGetAsEntry(); | |
1228 if (!entry.isFile) | |
1229 return; | |
1230 entry.file(this._loadFromFile.bind(this)); | |
1231 } | |
1232 }, | |
1233 | |
1234 _setAutoWindowTimes: function() | |
1235 { | |
1236 var tasks = this._model.mainThreadTasks(); | |
1237 if (!tasks.length) { | |
1238 this.requestWindowTimes(this._tracingModel.minimumRecordTime(), this
._tracingModel.maximumRecordTime()); | |
1239 return; | |
1240 } | |
1241 /** | |
1242 * @param {number} startIndex | |
1243 * @param {number} stopIndex | |
1244 * @return {number} | |
1245 */ | |
1246 function findLowUtilizationRegion(startIndex, stopIndex) | |
1247 { | |
1248 var /** @const */ threshold = 0.1; | |
1249 var cutIndex = startIndex; | |
1250 var cutTime = (tasks[cutIndex].startTime() + tasks[cutIndex].endTime
()) / 2; | |
1251 var usedTime = 0; | |
1252 var step = Math.sign(stopIndex - startIndex); | |
1253 for (var i = startIndex; i !== stopIndex; i += step) { | |
1254 var task = tasks[i]; | |
1255 var taskTime = (task.startTime() + task.endTime()) / 2; | |
1256 var interval = Math.abs(cutTime - taskTime); | |
1257 if (usedTime < threshold * interval) { | |
1258 cutIndex = i; | |
1259 cutTime = taskTime; | |
1260 usedTime = 0; | |
1261 } | |
1262 usedTime += task.endTime() - task.startTime(); | |
1263 } | |
1264 return cutIndex; | |
1265 } | |
1266 var rightIndex = findLowUtilizationRegion(tasks.length - 1, 0); | |
1267 var leftIndex = findLowUtilizationRegion(0, rightIndex); | |
1268 var leftTime = tasks[leftIndex].startTime(); | |
1269 var rightTime = tasks[rightIndex].endTime(); | |
1270 var span = rightTime - leftTime; | |
1271 var totalSpan = this._tracingModel.maximumRecordTime() - this._tracingMo
del.minimumRecordTime(); | |
1272 if (span < totalSpan * 0.1) { | |
1273 leftTime = this._tracingModel.minimumRecordTime(); | |
1274 rightTime = this._tracingModel.maximumRecordTime(); | |
1275 } else { | |
1276 leftTime = Math.max(leftTime - 0.05 * span, this._tracingModel.minim
umRecordTime()); | |
1277 rightTime = Math.min(rightTime + 0.05 * span, this._tracingModel.max
imumRecordTime()); | |
1278 } | |
1279 this.requestWindowTimes(leftTime, rightTime); | |
1280 }, | |
1281 | |
1282 __proto__: WebInspector.Panel.prototype | |
1283 }; | |
1284 | |
1285 /** | 1261 /** |
1286 * @interface | 1262 * @interface |
1287 */ | 1263 */ |
1288 WebInspector.TimelineLifecycleDelegate = function() | 1264 WebInspector.TimelineLifecycleDelegate = function() {}; |
1289 { | 1265 |
| 1266 WebInspector.TimelineLifecycleDelegate.prototype = { |
| 1267 recordingStarted: function() {}, |
| 1268 |
| 1269 /** |
| 1270 * @param {number} usage |
| 1271 */ |
| 1272 recordingProgress: function(usage) {}, |
| 1273 |
| 1274 loadingStarted: function() {}, |
| 1275 |
| 1276 /** |
| 1277 * @param {number=} progress |
| 1278 */ |
| 1279 loadingProgress: function(progress) {}, |
| 1280 |
| 1281 /** |
| 1282 * @param {boolean} success |
| 1283 */ |
| 1284 loadingComplete: function(success) {}, |
1290 }; | 1285 }; |
1291 | 1286 |
1292 WebInspector.TimelineLifecycleDelegate.prototype = { | |
1293 recordingStarted: function() {}, | |
1294 | |
1295 /** | |
1296 * @param {number} usage | |
1297 */ | |
1298 recordingProgress: function(usage) {}, | |
1299 | |
1300 loadingStarted: function() {}, | |
1301 | |
1302 /** | |
1303 * @param {number=} progress | |
1304 */ | |
1305 loadingProgress: function(progress) {}, | |
1306 | |
1307 /** | |
1308 * @param {boolean} success | |
1309 */ | |
1310 loadingComplete: function(success) {}, | |
1311 }; | |
1312 | |
1313 | |
1314 /** | 1287 /** |
1315 * @constructor | 1288 * @unrestricted |
1316 * @extends {WebInspector.TabbedPane} | |
1317 * @param {!WebInspector.TimelineModel} timelineModel | |
1318 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters | |
1319 * @param {!WebInspector.TimelineModeViewDelegate} delegate | |
1320 */ | 1289 */ |
1321 WebInspector.TimelineDetailsView = function(timelineModel, filters, delegate) | 1290 WebInspector.TimelineDetailsView = class extends WebInspector.TabbedPane { |
1322 { | 1291 /** |
1323 WebInspector.TabbedPane.call(this); | 1292 * @param {!WebInspector.TimelineModel} timelineModel |
1324 this.element.classList.add("timeline-details"); | 1293 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters |
| 1294 * @param {!WebInspector.TimelineModeViewDelegate} delegate |
| 1295 */ |
| 1296 constructor(timelineModel, filters, delegate) { |
| 1297 super(); |
| 1298 this.element.classList.add('timeline-details'); |
1325 | 1299 |
1326 var tabIds = WebInspector.TimelinePanel.DetailsTab; | 1300 var tabIds = WebInspector.TimelinePanel.DetailsTab; |
1327 this._defaultDetailsWidget = new WebInspector.VBox(); | 1301 this._defaultDetailsWidget = new WebInspector.VBox(); |
1328 this._defaultDetailsWidget.element.classList.add("timeline-details-view"); | 1302 this._defaultDetailsWidget.element.classList.add('timeline-details-view'); |
1329 this._defaultDetailsContentElement = this._defaultDetailsWidget.element.crea
teChild("div", "timeline-details-view-body vbox"); | 1303 this._defaultDetailsContentElement = |
1330 this.appendTab(tabIds.Details, WebInspector.UIString("Summary"), this._defau
ltDetailsWidget); | 1304 this._defaultDetailsWidget.element.createChild('div', 'timeline-details-
view-body vbox'); |
| 1305 this.appendTab(tabIds.Details, WebInspector.UIString('Summary'), this._defau
ltDetailsWidget); |
1331 this.setPreferredTab(tabIds.Details); | 1306 this.setPreferredTab(tabIds.Details); |
1332 | 1307 |
1333 /** @type Map<string, WebInspector.TimelineTreeView> */ | 1308 /** @type Map<string, WebInspector.TimelineTreeView> */ |
1334 this._rangeDetailViews = new Map(); | 1309 this._rangeDetailViews = new Map(); |
1335 | 1310 |
1336 var bottomUpView = new WebInspector.BottomUpTimelineTreeView(timelineModel,
filters); | 1311 var bottomUpView = new WebInspector.BottomUpTimelineTreeView(timelineModel,
filters); |
1337 this.appendTab(tabIds.BottomUp, WebInspector.UIString("Bottom-Up"), bottomUp
View); | 1312 this.appendTab(tabIds.BottomUp, WebInspector.UIString('Bottom-Up'), bottomUp
View); |
1338 this._rangeDetailViews.set(tabIds.BottomUp, bottomUpView); | 1313 this._rangeDetailViews.set(tabIds.BottomUp, bottomUpView); |
1339 | 1314 |
1340 var callTreeView = new WebInspector.CallTreeTimelineTreeView(timelineModel,
filters); | 1315 var callTreeView = new WebInspector.CallTreeTimelineTreeView(timelineModel,
filters); |
1341 this.appendTab(tabIds.CallTree, WebInspector.UIString("Call Tree"), callTree
View); | 1316 this.appendTab(tabIds.CallTree, WebInspector.UIString('Call Tree'), callTree
View); |
1342 this._rangeDetailViews.set(tabIds.CallTree, callTreeView); | 1317 this._rangeDetailViews.set(tabIds.CallTree, callTreeView); |
1343 | 1318 |
1344 var eventsView = new WebInspector.EventsTimelineTreeView(timelineModel, filt
ers, delegate); | 1319 var eventsView = new WebInspector.EventsTimelineTreeView(timelineModel, filt
ers, delegate); |
1345 this.appendTab(tabIds.Events, WebInspector.UIString("Event Log"), eventsView
); | 1320 this.appendTab(tabIds.Events, WebInspector.UIString('Event Log'), eventsView
); |
1346 this._rangeDetailViews.set(tabIds.Events, eventsView); | 1321 this._rangeDetailViews.set(tabIds.Events, eventsView); |
1347 | 1322 |
1348 this.addEventListener(WebInspector.TabbedPane.Events.TabSelected, this._tabS
elected, this); | 1323 this.addEventListener(WebInspector.TabbedPane.Events.TabSelected, this._tabS
elected, this); |
| 1324 } |
| 1325 |
| 1326 /** |
| 1327 * @param {!Node} node |
| 1328 */ |
| 1329 setContent(node) { |
| 1330 var allTabs = this.otherTabs(WebInspector.TimelinePanel.DetailsTab.Details); |
| 1331 for (var i = 0; i < allTabs.length; ++i) { |
| 1332 if (!this._rangeDetailViews.has(allTabs[i])) |
| 1333 this.closeTab(allTabs[i]); |
| 1334 } |
| 1335 this._defaultDetailsContentElement.removeChildren(); |
| 1336 this._defaultDetailsContentElement.appendChild(node); |
| 1337 } |
| 1338 |
| 1339 /** |
| 1340 * @param {!WebInspector.TimelineSelection} selection |
| 1341 */ |
| 1342 updateContents(selection) { |
| 1343 this._selection = selection; |
| 1344 var view = this.selectedTabId ? this._rangeDetailViews.get(this.selectedTabI
d) : null; |
| 1345 if (view) |
| 1346 view.updateContents(selection); |
| 1347 } |
| 1348 |
| 1349 /** |
| 1350 * @override |
| 1351 * @param {string} id |
| 1352 * @param {string} tabTitle |
| 1353 * @param {!WebInspector.Widget} view |
| 1354 * @param {string=} tabTooltip |
| 1355 * @param {boolean=} userGesture |
| 1356 * @param {boolean=} isCloseable |
| 1357 */ |
| 1358 appendTab(id, tabTitle, view, tabTooltip, userGesture, isCloseable) { |
| 1359 super.appendTab(id, tabTitle, view, tabTooltip, userGesture, isCloseable); |
| 1360 if (this._preferredTabId !== this.selectedTabId) |
| 1361 this.selectTab(id); |
| 1362 } |
| 1363 |
| 1364 /** |
| 1365 * @param {string} tabId |
| 1366 */ |
| 1367 setPreferredTab(tabId) { |
| 1368 this._preferredTabId = tabId; |
| 1369 } |
| 1370 |
| 1371 /** |
| 1372 * @param {!WebInspector.Event} event |
| 1373 */ |
| 1374 _tabSelected(event) { |
| 1375 if (!event.data.isUserGesture) |
| 1376 return; |
| 1377 this.setPreferredTab(event.data.tabId); |
| 1378 this.updateContents(this._selection); |
| 1379 } |
1349 }; | 1380 }; |
1350 | 1381 |
1351 WebInspector.TimelineDetailsView.prototype = { | |
1352 /** | |
1353 * @param {!Node} node | |
1354 */ | |
1355 setContent: function(node) | |
1356 { | |
1357 var allTabs = this.otherTabs(WebInspector.TimelinePanel.DetailsTab.Detai
ls); | |
1358 for (var i = 0; i < allTabs.length; ++i) { | |
1359 if (!this._rangeDetailViews.has(allTabs[i])) | |
1360 this.closeTab(allTabs[i]); | |
1361 } | |
1362 this._defaultDetailsContentElement.removeChildren(); | |
1363 this._defaultDetailsContentElement.appendChild(node); | |
1364 }, | |
1365 | |
1366 /** | |
1367 * @param {!WebInspector.TimelineSelection} selection | |
1368 */ | |
1369 updateContents: function(selection) | |
1370 { | |
1371 this._selection = selection; | |
1372 var view = this.selectedTabId ? this._rangeDetailViews.get(this.selected
TabId) : null; | |
1373 if (view) | |
1374 view.updateContents(selection); | |
1375 }, | |
1376 | |
1377 /** | |
1378 * @override | |
1379 * @param {string} id | |
1380 * @param {string} tabTitle | |
1381 * @param {!WebInspector.Widget} view | |
1382 * @param {string=} tabTooltip | |
1383 * @param {boolean=} userGesture | |
1384 * @param {boolean=} isCloseable | |
1385 */ | |
1386 appendTab: function(id, tabTitle, view, tabTooltip, userGesture, isCloseable
) | |
1387 { | |
1388 WebInspector.TabbedPane.prototype.appendTab.call(this, id, tabTitle, vie
w, tabTooltip, userGesture, isCloseable); | |
1389 if (this._preferredTabId !== this.selectedTabId) | |
1390 this.selectTab(id); | |
1391 }, | |
1392 | |
1393 /** | |
1394 * @param {string} tabId | |
1395 */ | |
1396 setPreferredTab: function(tabId) | |
1397 { | |
1398 this._preferredTabId = tabId; | |
1399 }, | |
1400 | |
1401 /** | |
1402 * @param {!WebInspector.Event} event | |
1403 */ | |
1404 _tabSelected: function(event) | |
1405 { | |
1406 if (!event.data.isUserGesture) | |
1407 return; | |
1408 this.setPreferredTab(event.data.tabId); | |
1409 this.updateContents(this._selection); | |
1410 }, | |
1411 | |
1412 __proto__: WebInspector.TabbedPane.prototype | |
1413 }; | |
1414 | |
1415 /** | 1382 /** |
1416 * @constructor | 1383 * @unrestricted |
1417 * @param {!WebInspector.TimelineSelection.Type} type | |
1418 * @param {number} startTime | |
1419 * @param {number} endTime | |
1420 * @param {!Object=} object | |
1421 */ | 1384 */ |
1422 WebInspector.TimelineSelection = function(type, startTime, endTime, object) | 1385 WebInspector.TimelineSelection = class { |
1423 { | 1386 /** |
| 1387 * @param {!WebInspector.TimelineSelection.Type} type |
| 1388 * @param {number} startTime |
| 1389 * @param {number} endTime |
| 1390 * @param {!Object=} object |
| 1391 */ |
| 1392 constructor(type, startTime, endTime, object) { |
1424 this._type = type; | 1393 this._type = type; |
1425 this._startTime = startTime; | 1394 this._startTime = startTime; |
1426 this._endTime = endTime; | 1395 this._endTime = endTime; |
1427 this._object = object || null; | 1396 this._object = object || null; |
| 1397 } |
| 1398 |
| 1399 /** |
| 1400 * @param {!WebInspector.TimelineFrame} frame |
| 1401 * @return {!WebInspector.TimelineSelection} |
| 1402 */ |
| 1403 static fromFrame(frame) { |
| 1404 return new WebInspector.TimelineSelection( |
| 1405 WebInspector.TimelineSelection.Type.Frame, frame.startTime, frame.endTim
e, frame); |
| 1406 } |
| 1407 |
| 1408 /** |
| 1409 * @param {!WebInspector.TimelineModel.NetworkRequest} request |
| 1410 * @return {!WebInspector.TimelineSelection} |
| 1411 */ |
| 1412 static fromNetworkRequest(request) { |
| 1413 return new WebInspector.TimelineSelection( |
| 1414 WebInspector.TimelineSelection.Type.NetworkRequest, request.startTime, r
equest.endTime || request.startTime, |
| 1415 request); |
| 1416 } |
| 1417 |
| 1418 /** |
| 1419 * @param {!WebInspector.TracingModel.Event} event |
| 1420 * @return {!WebInspector.TimelineSelection} |
| 1421 */ |
| 1422 static fromTraceEvent(event) { |
| 1423 return new WebInspector.TimelineSelection( |
| 1424 WebInspector.TimelineSelection.Type.TraceEvent, event.startTime, event.e
ndTime || (event.startTime + 1), event); |
| 1425 } |
| 1426 |
| 1427 /** |
| 1428 * @param {number} startTime |
| 1429 * @param {number} endTime |
| 1430 * @return {!WebInspector.TimelineSelection} |
| 1431 */ |
| 1432 static fromRange(startTime, endTime) { |
| 1433 return new WebInspector.TimelineSelection(WebInspector.TimelineSelection.Typ
e.Range, startTime, endTime); |
| 1434 } |
| 1435 |
| 1436 /** |
| 1437 * @return {!WebInspector.TimelineSelection.Type} |
| 1438 */ |
| 1439 type() { |
| 1440 return this._type; |
| 1441 } |
| 1442 |
| 1443 /** |
| 1444 * @return {?Object} |
| 1445 */ |
| 1446 object() { |
| 1447 return this._object; |
| 1448 } |
| 1449 |
| 1450 /** |
| 1451 * @return {number} |
| 1452 */ |
| 1453 startTime() { |
| 1454 return this._startTime; |
| 1455 } |
| 1456 |
| 1457 /** |
| 1458 * @return {number} |
| 1459 */ |
| 1460 endTime() { |
| 1461 return this._endTime; |
| 1462 } |
1428 }; | 1463 }; |
1429 | 1464 |
1430 /** | 1465 /** |
1431 * @enum {string} | 1466 * @enum {string} |
1432 */ | 1467 */ |
1433 WebInspector.TimelineSelection.Type = { | 1468 WebInspector.TimelineSelection.Type = { |
1434 Frame: "Frame", | 1469 Frame: 'Frame', |
1435 NetworkRequest: "NetworkRequest", | 1470 NetworkRequest: 'NetworkRequest', |
1436 TraceEvent: "TraceEvent", | 1471 TraceEvent: 'TraceEvent', |
1437 Range: "Range" | 1472 Range: 'Range' |
1438 }; | 1473 }; |
1439 | 1474 |
1440 /** | |
1441 * @param {!WebInspector.TimelineFrame} frame | |
1442 * @return {!WebInspector.TimelineSelection} | |
1443 */ | |
1444 WebInspector.TimelineSelection.fromFrame = function(frame) | |
1445 { | |
1446 return new WebInspector.TimelineSelection( | |
1447 WebInspector.TimelineSelection.Type.Frame, | |
1448 frame.startTime, frame.endTime, | |
1449 frame); | |
1450 }; | |
1451 | |
1452 /** | |
1453 * @param {!WebInspector.TimelineModel.NetworkRequest} request | |
1454 * @return {!WebInspector.TimelineSelection} | |
1455 */ | |
1456 WebInspector.TimelineSelection.fromNetworkRequest = function(request) | |
1457 { | |
1458 return new WebInspector.TimelineSelection( | |
1459 WebInspector.TimelineSelection.Type.NetworkRequest, | |
1460 request.startTime, request.endTime || request.startTime, | |
1461 request); | |
1462 }; | |
1463 | |
1464 /** | |
1465 * @param {!WebInspector.TracingModel.Event} event | |
1466 * @return {!WebInspector.TimelineSelection} | |
1467 */ | |
1468 WebInspector.TimelineSelection.fromTraceEvent = function(event) | |
1469 { | |
1470 return new WebInspector.TimelineSelection( | |
1471 WebInspector.TimelineSelection.Type.TraceEvent, | |
1472 event.startTime, event.endTime || (event.startTime + 1), | |
1473 event); | |
1474 }; | |
1475 | |
1476 /** | |
1477 * @param {number} startTime | |
1478 * @param {number} endTime | |
1479 * @return {!WebInspector.TimelineSelection} | |
1480 */ | |
1481 WebInspector.TimelineSelection.fromRange = function(startTime, endTime) | |
1482 { | |
1483 return new WebInspector.TimelineSelection( | |
1484 WebInspector.TimelineSelection.Type.Range, | |
1485 startTime, endTime); | |
1486 }; | |
1487 | |
1488 WebInspector.TimelineSelection.prototype = { | |
1489 /** | |
1490 * @return {!WebInspector.TimelineSelection.Type} | |
1491 */ | |
1492 type: function() | |
1493 { | |
1494 return this._type; | |
1495 }, | |
1496 | |
1497 /** | |
1498 * @return {?Object} | |
1499 */ | |
1500 object: function() | |
1501 { | |
1502 return this._object; | |
1503 }, | |
1504 | |
1505 /** | |
1506 * @return {number} | |
1507 */ | |
1508 startTime: function() | |
1509 { | |
1510 return this._startTime; | |
1511 }, | |
1512 | |
1513 /** | |
1514 * @return {number} | |
1515 */ | |
1516 endTime: function() | |
1517 { | |
1518 return this._endTime; | |
1519 } | |
1520 }; | |
1521 | 1475 |
1522 /** | 1476 /** |
1523 * @interface | 1477 * @interface |
1524 * @extends {WebInspector.EventTarget} | 1478 * @extends {WebInspector.EventTarget} |
1525 */ | 1479 */ |
1526 WebInspector.TimelineModeView = function() | 1480 WebInspector.TimelineModeView = function() {}; |
1527 { | 1481 |
| 1482 WebInspector.TimelineModeView.prototype = { |
| 1483 /** |
| 1484 * @return {!WebInspector.Widget} |
| 1485 */ |
| 1486 view: function() {}, |
| 1487 |
| 1488 dispose: function() {}, |
| 1489 |
| 1490 /** |
| 1491 * @return {?Element} |
| 1492 */ |
| 1493 resizerElement: function() {}, |
| 1494 |
| 1495 reset: function() {}, |
| 1496 |
| 1497 refreshRecords: function() {}, |
| 1498 |
| 1499 /** |
| 1500 * @param {?WebInspector.TracingModel.Event} event |
| 1501 * @param {string=} regex |
| 1502 * @param {boolean=} select |
| 1503 */ |
| 1504 highlightSearchResult: function(event, regex, select) {}, |
| 1505 |
| 1506 /** |
| 1507 * @param {number} startTime |
| 1508 * @param {number} endTime |
| 1509 */ |
| 1510 setWindowTimes: function(startTime, endTime) {}, |
| 1511 |
| 1512 /** |
| 1513 * @param {?WebInspector.TimelineSelection} selection |
| 1514 */ |
| 1515 setSelection: function(selection) {}, |
| 1516 |
| 1517 /** |
| 1518 * @param {?WebInspector.TracingModel.Event} event |
| 1519 */ |
| 1520 highlightEvent: function(event) {} |
1528 }; | 1521 }; |
1529 | 1522 |
1530 WebInspector.TimelineModeView.prototype = { | |
1531 /** | |
1532 * @return {!WebInspector.Widget} | |
1533 */ | |
1534 view: function() {}, | |
1535 | |
1536 dispose: function() {}, | |
1537 | |
1538 /** | |
1539 * @return {?Element} | |
1540 */ | |
1541 resizerElement: function() {}, | |
1542 | |
1543 reset: function() {}, | |
1544 | |
1545 refreshRecords: function() {}, | |
1546 | |
1547 /** | |
1548 * @param {?WebInspector.TracingModel.Event} event | |
1549 * @param {string=} regex | |
1550 * @param {boolean=} select | |
1551 */ | |
1552 highlightSearchResult: function(event, regex, select) {}, | |
1553 | |
1554 /** | |
1555 * @param {number} startTime | |
1556 * @param {number} endTime | |
1557 */ | |
1558 setWindowTimes: function(startTime, endTime) {}, | |
1559 | |
1560 /** | |
1561 * @param {?WebInspector.TimelineSelection} selection | |
1562 */ | |
1563 setSelection: function(selection) {}, | |
1564 | |
1565 /** | |
1566 * @param {?WebInspector.TracingModel.Event} event | |
1567 */ | |
1568 highlightEvent: function(event) { } | |
1569 }; | |
1570 | |
1571 /** | 1523 /** |
1572 * @interface | 1524 * @interface |
1573 */ | 1525 */ |
1574 WebInspector.TimelineModeViewDelegate = function() {}; | 1526 WebInspector.TimelineModeViewDelegate = function() {}; |
1575 | 1527 |
1576 WebInspector.TimelineModeViewDelegate.prototype = { | 1528 WebInspector.TimelineModeViewDelegate.prototype = { |
1577 /** | 1529 /** |
1578 * @param {number} startTime | 1530 * @param {number} startTime |
1579 * @param {number} endTime | 1531 * @param {number} endTime |
1580 */ | 1532 */ |
1581 requestWindowTimes: function(startTime, endTime) {}, | 1533 requestWindowTimes: function(startTime, endTime) {}, |
1582 | 1534 |
1583 /** | 1535 /** |
1584 * @param {?WebInspector.TimelineSelection} selection | 1536 * @param {?WebInspector.TimelineSelection} selection |
1585 * @param {!WebInspector.TimelinePanel.DetailsTab=} preferredTab | 1537 * @param {!WebInspector.TimelinePanel.DetailsTab=} preferredTab |
1586 */ | 1538 */ |
1587 select: function(selection, preferredTab) {}, | 1539 select: function(selection, preferredTab) {}, |
1588 | 1540 |
1589 /** | 1541 /** |
1590 * @param {number} time | 1542 * @param {number} time |
1591 */ | 1543 */ |
1592 selectEntryAtTime: function(time) {}, | 1544 selectEntryAtTime: function(time) {}, |
1593 | 1545 |
1594 /** | 1546 /** |
1595 * @param {!Node} node | 1547 * @param {!Node} node |
1596 */ | 1548 */ |
1597 showInDetails: function(node) {}, | 1549 showInDetails: function(node) {}, |
1598 | 1550 |
1599 /** | 1551 /** |
1600 * @param {?WebInspector.TracingModel.Event} event | 1552 * @param {?WebInspector.TracingModel.Event} event |
1601 */ | 1553 */ |
1602 highlightEvent: function(event) {} | 1554 highlightEvent: function(event) {} |
1603 }; | 1555 }; |
1604 | 1556 |
1605 /** | 1557 /** |
1606 * @constructor | 1558 * @unrestricted |
1607 * @extends {WebInspector.TimelineModel.Filter} | 1559 */ |
1608 */ | 1560 WebInspector.TimelineCategoryFilter = class extends WebInspector.TimelineModel.F
ilter { |
1609 WebInspector.TimelineCategoryFilter = function() | 1561 constructor() { |
1610 { | 1562 super(); |
1611 WebInspector.TimelineModel.Filter.call(this); | 1563 } |
1612 }; | 1564 |
1613 | 1565 /** |
1614 WebInspector.TimelineCategoryFilter.prototype = { | 1566 * @override |
1615 /** | 1567 * @param {!WebInspector.TracingModel.Event} event |
1616 * @override | 1568 * @return {boolean} |
1617 * @param {!WebInspector.TracingModel.Event} event | 1569 */ |
1618 * @return {boolean} | 1570 accept(event) { |
1619 */ | 1571 return !WebInspector.TimelineUIUtils.eventStyle(event).category.hidden; |
1620 accept: function(event) | 1572 } |
1621 { | 1573 }; |
1622 return !WebInspector.TimelineUIUtils.eventStyle(event).category.hidden; | 1574 |
1623 }, | 1575 /** |
1624 | 1576 * @unrestricted |
1625 __proto__: WebInspector.TimelineModel.Filter.prototype | 1577 */ |
1626 }; | 1578 WebInspector.TimelineIsLongFilter = class extends WebInspector.TimelineModel.Fil
ter { |
1627 | 1579 constructor() { |
1628 /** | 1580 super(); |
1629 * @constructor | |
1630 * @extends {WebInspector.TimelineModel.Filter} | |
1631 */ | |
1632 WebInspector.TimelineIsLongFilter = function() | |
1633 { | |
1634 WebInspector.TimelineModel.Filter.call(this); | |
1635 this._minimumRecordDuration = 0; | 1581 this._minimumRecordDuration = 0; |
1636 }; | 1582 } |
1637 | 1583 |
1638 WebInspector.TimelineIsLongFilter.prototype = { | 1584 /** |
1639 /** | 1585 * @param {number} value |
1640 * @param {number} value | 1586 */ |
1641 */ | 1587 setMinimumRecordDuration(value) { |
1642 setMinimumRecordDuration: function(value) | 1588 this._minimumRecordDuration = value; |
1643 { | 1589 } |
1644 this._minimumRecordDuration = value; | 1590 |
1645 }, | 1591 /** |
1646 | 1592 * @override |
1647 /** | 1593 * @param {!WebInspector.TracingModel.Event} event |
1648 * @override | 1594 * @return {boolean} |
1649 * @param {!WebInspector.TracingModel.Event} event | 1595 */ |
1650 * @return {boolean} | 1596 accept(event) { |
1651 */ | 1597 var duration = event.endTime ? event.endTime - event.startTime : 0; |
1652 accept: function(event) | 1598 return duration >= this._minimumRecordDuration; |
1653 { | 1599 } |
1654 var duration = event.endTime ? event.endTime - event.startTime : 0; | 1600 }; |
1655 return duration >= this._minimumRecordDuration; | 1601 |
1656 }, | 1602 /** |
1657 | 1603 * @unrestricted |
1658 __proto__: WebInspector.TimelineModel.Filter.prototype | 1604 */ |
1659 | 1605 WebInspector.TimelineTextFilter = class extends WebInspector.TimelineModel.Filte
r { |
1660 }; | 1606 /** |
1661 | 1607 * @param {!RegExp=} regExp |
1662 /** | 1608 */ |
1663 * @constructor | 1609 constructor(regExp) { |
1664 * @extends {WebInspector.TimelineModel.Filter} | 1610 super(); |
1665 * @param {!RegExp=} regExp | |
1666 */ | |
1667 WebInspector.TimelineTextFilter = function(regExp) | |
1668 { | |
1669 WebInspector.TimelineModel.Filter.call(this); | |
1670 this._setRegExp(regExp || null); | 1611 this._setRegExp(regExp || null); |
1671 }; | 1612 } |
1672 | 1613 |
1673 WebInspector.TimelineTextFilter.prototype = { | 1614 /** |
1674 /** | 1615 * @param {?RegExp} regExp |
1675 * @param {?RegExp} regExp | 1616 */ |
1676 */ | 1617 _setRegExp(regExp) { |
1677 _setRegExp: function(regExp) | 1618 this._regExp = regExp; |
1678 { | 1619 } |
1679 this._regExp = regExp; | 1620 |
1680 }, | 1621 /** |
1681 | 1622 * @override |
1682 /** | 1623 * @param {!WebInspector.TracingModel.Event} event |
1683 * @override | 1624 * @return {boolean} |
1684 * @param {!WebInspector.TracingModel.Event} event | 1625 */ |
1685 * @return {boolean} | 1626 accept(event) { |
1686 */ | 1627 return !this._regExp || WebInspector.TimelineUIUtils.testContentMatching(eve
nt, this._regExp); |
1687 accept: function(event) | 1628 } |
1688 { | 1629 }; |
1689 return !this._regExp || WebInspector.TimelineUIUtils.testContentMatching
(event, this._regExp); | 1630 |
1690 }, | 1631 /** |
1691 | 1632 * @unrestricted |
1692 __proto__: WebInspector.TimelineModel.Filter.prototype | 1633 */ |
1693 }; | 1634 WebInspector.TimelinePanel.StatusPane = class extends WebInspector.VBox { |
1694 | 1635 /** |
1695 /** | 1636 * @param {boolean} showTimer |
1696 * @constructor | 1637 * @param {function()} stopCallback |
1697 * @extends {WebInspector.VBox} | 1638 */ |
1698 * @param {boolean} showTimer | 1639 constructor(showTimer, stopCallback) { |
1699 * @param {function()} stopCallback | 1640 super(true); |
1700 */ | 1641 this.registerRequiredCSS('timeline/timelineStatusDialog.css'); |
1701 WebInspector.TimelinePanel.StatusPane = function(showTimer, stopCallback) | 1642 this.contentElement.classList.add('timeline-status-dialog'); |
1702 { | 1643 |
1703 WebInspector.VBox.call(this, true); | 1644 var statusLine = this.contentElement.createChild('div', 'status-dialog-line
status'); |
1704 this.registerRequiredCSS("timeline/timelineStatusDialog.css"); | 1645 statusLine.createChild('div', 'label').textContent = WebInspector.UIString('
Status'); |
1705 this.contentElement.classList.add("timeline-status-dialog"); | 1646 this._status = statusLine.createChild('div', 'content'); |
1706 | |
1707 var statusLine = this.contentElement.createChild("div", "status-dialog-line
status"); | |
1708 statusLine.createChild("div", "label").textContent = WebInspector.UIString("
Status"); | |
1709 this._status = statusLine.createChild("div", "content"); | |
1710 | 1647 |
1711 if (showTimer) { | 1648 if (showTimer) { |
1712 var timeLine = this.contentElement.createChild("div", "status-dialog-lin
e time"); | 1649 var timeLine = this.contentElement.createChild('div', 'status-dialog-line
time'); |
1713 timeLine.createChild("div", "label").textContent = WebInspector.UIString
("Time"); | 1650 timeLine.createChild('div', 'label').textContent = WebInspector.UIString('
Time'); |
1714 this._time = timeLine.createChild("div", "content"); | 1651 this._time = timeLine.createChild('div', 'content'); |
1715 } | 1652 } |
1716 var progressLine = this.contentElement.createChild("div", "status-dialog-lin
e progress"); | 1653 var progressLine = this.contentElement.createChild('div', 'status-dialog-lin
e progress'); |
1717 this._progressLabel = progressLine.createChild("div", "label"); | 1654 this._progressLabel = progressLine.createChild('div', 'label'); |
1718 this._progressBar = progressLine.createChild("div", "indicator-container").c
reateChild("div", "indicator"); | 1655 this._progressBar = progressLine.createChild('div', 'indicator-container').c
reateChild('div', 'indicator'); |
1719 | 1656 |
1720 this._stopButton = createTextButton(WebInspector.UIString("Stop"), stopCallb
ack); | 1657 this._stopButton = createTextButton(WebInspector.UIString('Stop'), stopCallb
ack); |
1721 this.contentElement.createChild("div", "stop-button").appendChild(this._stop
Button); | 1658 this.contentElement.createChild('div', 'stop-button').appendChild(this._stop
Button); |
1722 }; | 1659 } |
1723 | 1660 |
1724 WebInspector.TimelinePanel.StatusPane.prototype = { | 1661 finish() { |
1725 finish: function() | 1662 this._stopTimer(); |
1726 { | 1663 this._stopButton.disabled = true; |
1727 this._stopTimer(); | 1664 } |
1728 this._stopButton.disabled = true; | 1665 |
1729 }, | 1666 hide() { |
1730 | 1667 this.element.parentNode.classList.remove('tinted'); |
1731 hide: function() | 1668 this.element.remove(); |
1732 { | 1669 } |
1733 this.element.parentNode.classList.remove("tinted"); | 1670 |
1734 this.element.remove(); | 1671 /** |
1735 }, | 1672 * @param {!Element} parent |
1736 | 1673 */ |
1737 /** | 1674 showPane(parent) { |
1738 * @param {!Element} parent | 1675 this.show(parent); |
1739 */ | 1676 parent.classList.add('tinted'); |
1740 showPane: function(parent) | 1677 } |
1741 { | 1678 |
1742 this.show(parent); | 1679 /** |
1743 parent.classList.add("tinted"); | 1680 * @param {string} text |
1744 }, | 1681 */ |
1745 | 1682 updateStatus(text) { |
1746 /** | 1683 this._status.textContent = text; |
1747 * @param {string} text | 1684 } |
1748 */ | 1685 |
1749 updateStatus: function(text) | 1686 /** |
1750 { | 1687 * @param {string} activity |
1751 this._status.textContent = text; | 1688 * @param {number} percent |
1752 }, | 1689 */ |
1753 | 1690 updateProgressBar(activity, percent) { |
1754 /** | 1691 this._progressLabel.textContent = activity; |
1755 * @param {string} activity | 1692 this._progressBar.style.width = percent.toFixed(1) + '%'; |
1756 * @param {number} percent | 1693 this._updateTimer(); |
1757 */ | 1694 } |
1758 updateProgressBar: function(activity, percent) | 1695 |
1759 { | 1696 startTimer() { |
1760 this._progressLabel.textContent = activity; | 1697 this._startTime = Date.now(); |
1761 this._progressBar.style.width = percent.toFixed(1) + "%"; | 1698 this._timeUpdateTimer = setInterval(this._updateTimer.bind(this, false), 100
0); |
1762 this._updateTimer(); | 1699 this._updateTimer(); |
1763 }, | 1700 } |
1764 | 1701 |
1765 startTimer: function() | 1702 _stopTimer() { |
1766 { | 1703 if (!this._timeUpdateTimer) |
1767 this._startTime = Date.now(); | 1704 return; |
1768 this._timeUpdateTimer = setInterval(this._updateTimer.bind(this, false),
1000); | 1705 clearInterval(this._timeUpdateTimer); |
1769 this._updateTimer(); | 1706 this._updateTimer(true); |
1770 }, | 1707 delete this._timeUpdateTimer; |
1771 | 1708 } |
1772 _stopTimer: function() | 1709 |
1773 { | 1710 /** |
1774 if (!this._timeUpdateTimer) | 1711 * @param {boolean=} precise |
1775 return; | 1712 */ |
1776 clearInterval(this._timeUpdateTimer); | 1713 _updateTimer(precise) { |
1777 this._updateTimer(true); | 1714 if (!this._timeUpdateTimer) |
1778 delete this._timeUpdateTimer; | 1715 return; |
1779 }, | 1716 var elapsed = (Date.now() - this._startTime) / 1000; |
1780 | 1717 this._time.textContent = WebInspector.UIString('%s\u2009sec', elapsed.toFixe
d(precise ? 1 : 0)); |
1781 /** | 1718 } |
1782 * @param {boolean=} precise | 1719 }; |
1783 */ | 1720 |
1784 _updateTimer: function(precise) | 1721 |
1785 { | 1722 /** |
1786 if (!this._timeUpdateTimer) | |
1787 return; | |
1788 var elapsed = (Date.now() - this._startTime) / 1000; | |
1789 this._time.textContent = WebInspector.UIString("%s\u2009sec", elapsed.to
Fixed(precise ? 1 : 0)); | |
1790 }, | |
1791 | |
1792 __proto__: WebInspector.VBox.prototype | |
1793 }; | |
1794 | |
1795 /** | |
1796 * @return {!WebInspector.TimelinePanel} | |
1797 */ | |
1798 WebInspector.TimelinePanel.instance = function() | |
1799 { | |
1800 return /** @type {!WebInspector.TimelinePanel} */ (self.runtime.sharedInstan
ce(WebInspector.TimelinePanel)); | |
1801 }; | |
1802 | |
1803 /** | |
1804 * @constructor | |
1805 * @implements {WebInspector.QueryParamHandler} | 1723 * @implements {WebInspector.QueryParamHandler} |
1806 */ | 1724 * @unrestricted |
1807 WebInspector.LoadTimelineHandler = function() | 1725 */ |
1808 { | 1726 WebInspector.LoadTimelineHandler = class { |
1809 }; | 1727 /** |
1810 | 1728 * @override |
1811 WebInspector.LoadTimelineHandler.prototype = { | 1729 * @param {string} value |
1812 /** | 1730 */ |
1813 * @override | 1731 handleQueryParam(value) { |
1814 * @param {string} value | 1732 WebInspector.viewManager.showView('timeline').then(() => { |
1815 */ | 1733 WebInspector.TimelinePanel.instance()._loadFromURL(window.decodeURICompone
nt(value)); |
1816 handleQueryParam: function(value) | 1734 }); |
1817 { | 1735 } |
1818 WebInspector.viewManager.showView("timeline").then(() => { | 1736 }; |
1819 WebInspector.TimelinePanel.instance()._loadFromURL(window.decodeURIC
omponent(value)); | 1737 |
1820 }); | 1738 /** |
| 1739 * @implements {WebInspector.ActionDelegate} |
| 1740 * @unrestricted |
| 1741 */ |
| 1742 WebInspector.TimelinePanel.ActionDelegate = class { |
| 1743 /** |
| 1744 * @override |
| 1745 * @param {!WebInspector.Context} context |
| 1746 * @param {string} actionId |
| 1747 * @return {boolean} |
| 1748 */ |
| 1749 handleAction(context, actionId) { |
| 1750 var panel = WebInspector.context.flavor(WebInspector.TimelinePanel); |
| 1751 console.assert(panel && panel instanceof WebInspector.TimelinePanel); |
| 1752 switch (actionId) { |
| 1753 case 'timeline.toggle-recording': |
| 1754 panel._toggleRecording(); |
| 1755 return true; |
| 1756 case 'timeline.save-to-file': |
| 1757 panel._saveToFile(); |
| 1758 return true; |
| 1759 case 'timeline.load-from-file': |
| 1760 panel._selectFileToLoad(); |
| 1761 return true; |
| 1762 case 'timeline.jump-to-previous-frame': |
| 1763 panel._jumpToFrame(-1); |
| 1764 return true; |
| 1765 case 'timeline.jump-to-next-frame': |
| 1766 panel._jumpToFrame(1); |
| 1767 return true; |
1821 } | 1768 } |
1822 }; | 1769 return false; |
1823 | 1770 } |
1824 /** | 1771 }; |
1825 * @constructor | 1772 |
1826 * @implements {WebInspector.ActionDelegate} | 1773 /** |
1827 */ | 1774 * @unrestricted |
1828 WebInspector.TimelinePanel.ActionDelegate = function() | 1775 */ |
1829 { | 1776 WebInspector.TimelineFilters = class extends WebInspector.Object { |
1830 }; | 1777 constructor() { |
1831 | 1778 super(); |
1832 WebInspector.TimelinePanel.ActionDelegate.prototype = { | |
1833 /** | |
1834 * @override | |
1835 * @param {!WebInspector.Context} context | |
1836 * @param {string} actionId | |
1837 * @return {boolean} | |
1838 */ | |
1839 handleAction: function(context, actionId) | |
1840 { | |
1841 var panel = WebInspector.context.flavor(WebInspector.TimelinePanel); | |
1842 console.assert(panel && panel instanceof WebInspector.TimelinePanel); | |
1843 switch (actionId) { | |
1844 case "timeline.toggle-recording": | |
1845 panel._toggleRecording(); | |
1846 return true; | |
1847 case "timeline.save-to-file": | |
1848 panel._saveToFile(); | |
1849 return true; | |
1850 case "timeline.load-from-file": | |
1851 panel._selectFileToLoad(); | |
1852 return true; | |
1853 case "timeline.jump-to-previous-frame": | |
1854 panel._jumpToFrame(-1); | |
1855 return true; | |
1856 case "timeline.jump-to-next-frame": | |
1857 panel._jumpToFrame(1); | |
1858 return true; | |
1859 } | |
1860 return false; | |
1861 } | |
1862 }; | |
1863 | |
1864 /** | |
1865 * @constructor | |
1866 * @extends {WebInspector.Object} | |
1867 */ | |
1868 WebInspector.TimelineFilters = function() | |
1869 { | |
1870 WebInspector.Object.call(this); | |
1871 | 1779 |
1872 this._categoryFilter = new WebInspector.TimelineCategoryFilter(); | 1780 this._categoryFilter = new WebInspector.TimelineCategoryFilter(); |
1873 this._durationFilter = new WebInspector.TimelineIsLongFilter(); | 1781 this._durationFilter = new WebInspector.TimelineIsLongFilter(); |
1874 this._textFilter = new WebInspector.TimelineTextFilter(); | 1782 this._textFilter = new WebInspector.TimelineTextFilter(); |
1875 this._filters = [this._categoryFilter, this._durationFilter, this._textFilte
r]; | 1783 this._filters = [this._categoryFilter, this._durationFilter, this._textFilte
r]; |
1876 | 1784 |
1877 this._createFilterBar(); | 1785 this._createFilterBar(); |
| 1786 } |
| 1787 |
| 1788 /** |
| 1789 * @return {!Array<!WebInspector.TimelineModel.Filter>} |
| 1790 */ |
| 1791 filters() { |
| 1792 return this._filters; |
| 1793 } |
| 1794 |
| 1795 /** |
| 1796 * @return {?RegExp} |
| 1797 */ |
| 1798 searchRegExp() { |
| 1799 return this._textFilter._regExp; |
| 1800 } |
| 1801 |
| 1802 /** |
| 1803 * @return {!WebInspector.ToolbarItem} |
| 1804 */ |
| 1805 filterButton() { |
| 1806 return this._filterBar.filterButton(); |
| 1807 } |
| 1808 |
| 1809 /** |
| 1810 * @return {!WebInspector.Widget} |
| 1811 */ |
| 1812 filtersWidget() { |
| 1813 return this._filterBar; |
| 1814 } |
| 1815 |
| 1816 _createFilterBar() { |
| 1817 this._filterBar = new WebInspector.FilterBar('timelinePanel'); |
| 1818 |
| 1819 this._textFilterUI = new WebInspector.TextFilterUI(); |
| 1820 this._textFilterUI.addEventListener(WebInspector.FilterUI.Events.FilterChang
ed, textFilterChanged, this); |
| 1821 this._filterBar.addFilter(this._textFilterUI); |
| 1822 |
| 1823 var durationOptions = []; |
| 1824 for (var durationMs of WebInspector.TimelineFilters._durationFilterPresetsMs
) { |
| 1825 var durationOption = {}; |
| 1826 if (!durationMs) { |
| 1827 durationOption.label = WebInspector.UIString('All'); |
| 1828 durationOption.title = WebInspector.UIString('Show all records'); |
| 1829 } else { |
| 1830 durationOption.label = WebInspector.UIString('\u2265 %dms', durationMs); |
| 1831 durationOption.title = WebInspector.UIString('Hide records shorter than
%dms', durationMs); |
| 1832 } |
| 1833 durationOption.value = durationMs; |
| 1834 durationOptions.push(durationOption); |
| 1835 } |
| 1836 var durationFilterUI = new WebInspector.ComboBoxFilterUI(durationOptions); |
| 1837 durationFilterUI.addEventListener(WebInspector.FilterUI.Events.FilterChanged
, durationFilterChanged, this); |
| 1838 this._filterBar.addFilter(durationFilterUI); |
| 1839 |
| 1840 var categoryFiltersUI = {}; |
| 1841 var categories = WebInspector.TimelineUIUtils.categories(); |
| 1842 for (var categoryName in categories) { |
| 1843 var category = categories[categoryName]; |
| 1844 if (!category.visible) |
| 1845 continue; |
| 1846 var filter = new WebInspector.CheckboxFilterUI(category.name, category.tit
le); |
| 1847 filter.setColor(category.color, 'rgba(0, 0, 0, 0.2)'); |
| 1848 categoryFiltersUI[category.name] = filter; |
| 1849 filter.addEventListener( |
| 1850 WebInspector.FilterUI.Events.FilterChanged, categoriesFilterChanged.bi
nd(this, categoryName)); |
| 1851 this._filterBar.addFilter(filter); |
| 1852 } |
| 1853 return this._filterBar; |
| 1854 |
| 1855 /** |
| 1856 * @this {WebInspector.TimelineFilters} |
| 1857 */ |
| 1858 function textFilterChanged() { |
| 1859 var searchQuery = this._textFilterUI.value(); |
| 1860 this._textFilter._setRegExp(searchQuery ? createPlainTextSearchRegex(searc
hQuery, 'i') : null); |
| 1861 this._notifyFiltersChanged(); |
| 1862 } |
| 1863 |
| 1864 /** |
| 1865 * @this {WebInspector.TimelineFilters} |
| 1866 */ |
| 1867 function durationFilterChanged() { |
| 1868 var duration = durationFilterUI.value(); |
| 1869 var minimumRecordDuration = parseInt(duration, 10); |
| 1870 this._durationFilter.setMinimumRecordDuration(minimumRecordDuration); |
| 1871 this._notifyFiltersChanged(); |
| 1872 } |
| 1873 |
| 1874 /** |
| 1875 * @param {string} name |
| 1876 * @this {WebInspector.TimelineFilters} |
| 1877 */ |
| 1878 function categoriesFilterChanged(name) { |
| 1879 var categories = WebInspector.TimelineUIUtils.categories(); |
| 1880 categories[name].hidden = !categoryFiltersUI[name].checked(); |
| 1881 this._notifyFiltersChanged(); |
| 1882 } |
| 1883 } |
| 1884 |
| 1885 _notifyFiltersChanged() { |
| 1886 this.dispatchEventToListeners(WebInspector.TimelineFilters.Events.FilterChan
ged); |
| 1887 } |
1878 }; | 1888 }; |
1879 | 1889 |
1880 /** @enum {symbol} */ | 1890 /** @enum {symbol} */ |
1881 WebInspector.TimelineFilters.Events = { | 1891 WebInspector.TimelineFilters.Events = { |
1882 FilterChanged: Symbol("FilterChanged") | 1892 FilterChanged: Symbol('FilterChanged') |
1883 }; | 1893 }; |
1884 | 1894 |
1885 WebInspector.TimelineFilters._durationFilterPresetsMs = [0, 1, 15]; | 1895 WebInspector.TimelineFilters._durationFilterPresetsMs = [0, 1, 15]; |
1886 | 1896 |
1887 WebInspector.TimelineFilters.prototype = { | |
1888 /** | |
1889 * @return {!Array<!WebInspector.TimelineModel.Filter>} | |
1890 */ | |
1891 filters: function() | |
1892 { | |
1893 return this._filters; | |
1894 }, | |
1895 | |
1896 /** | |
1897 * @return {?RegExp} | |
1898 */ | |
1899 searchRegExp: function() | |
1900 { | |
1901 return this._textFilter._regExp; | |
1902 }, | |
1903 | |
1904 /** | |
1905 * @return {!WebInspector.ToolbarItem} | |
1906 */ | |
1907 filterButton: function() | |
1908 { | |
1909 return this._filterBar.filterButton(); | |
1910 }, | |
1911 | |
1912 /** | |
1913 * @return {!WebInspector.Widget} | |
1914 */ | |
1915 filtersWidget: function() | |
1916 { | |
1917 return this._filterBar; | |
1918 }, | |
1919 | |
1920 _createFilterBar: function() | |
1921 { | |
1922 this._filterBar = new WebInspector.FilterBar("timelinePanel"); | |
1923 | |
1924 this._textFilterUI = new WebInspector.TextFilterUI(); | |
1925 this._textFilterUI.addEventListener(WebInspector.FilterUI.Events.FilterC
hanged, textFilterChanged, this); | |
1926 this._filterBar.addFilter(this._textFilterUI); | |
1927 | |
1928 var durationOptions = []; | |
1929 for (var durationMs of WebInspector.TimelineFilters._durationFilterPrese
tsMs) { | |
1930 var durationOption = {}; | |
1931 if (!durationMs) { | |
1932 durationOption.label = WebInspector.UIString("All"); | |
1933 durationOption.title = WebInspector.UIString("Show all records")
; | |
1934 } else { | |
1935 durationOption.label = WebInspector.UIString("\u2265 %dms", dura
tionMs); | |
1936 durationOption.title = WebInspector.UIString("Hide records short
er than %dms", durationMs); | |
1937 } | |
1938 durationOption.value = durationMs; | |
1939 durationOptions.push(durationOption); | |
1940 } | |
1941 var durationFilterUI = new WebInspector.ComboBoxFilterUI(durationOptions
); | |
1942 durationFilterUI.addEventListener(WebInspector.FilterUI.Events.FilterCha
nged, durationFilterChanged, this); | |
1943 this._filterBar.addFilter(durationFilterUI); | |
1944 | |
1945 var categoryFiltersUI = {}; | |
1946 var categories = WebInspector.TimelineUIUtils.categories(); | |
1947 for (var categoryName in categories) { | |
1948 var category = categories[categoryName]; | |
1949 if (!category.visible) | |
1950 continue; | |
1951 var filter = new WebInspector.CheckboxFilterUI(category.name, catego
ry.title); | |
1952 filter.setColor(category.color, "rgba(0, 0, 0, 0.2)"); | |
1953 categoryFiltersUI[category.name] = filter; | |
1954 filter.addEventListener(WebInspector.FilterUI.Events.FilterChanged,
categoriesFilterChanged.bind(this, categoryName)); | |
1955 this._filterBar.addFilter(filter); | |
1956 } | |
1957 return this._filterBar; | |
1958 | |
1959 /** | |
1960 * @this {WebInspector.TimelineFilters} | |
1961 */ | |
1962 function textFilterChanged() | |
1963 { | |
1964 var searchQuery = this._textFilterUI.value(); | |
1965 this._textFilter._setRegExp(searchQuery ? createPlainTextSearchRegex
(searchQuery, "i") : null); | |
1966 this._notifyFiltersChanged(); | |
1967 } | |
1968 | |
1969 /** | |
1970 * @this {WebInspector.TimelineFilters} | |
1971 */ | |
1972 function durationFilterChanged() | |
1973 { | |
1974 var duration = durationFilterUI.value(); | |
1975 var minimumRecordDuration = parseInt(duration, 10); | |
1976 this._durationFilter.setMinimumRecordDuration(minimumRecordDuration)
; | |
1977 this._notifyFiltersChanged(); | |
1978 } | |
1979 | |
1980 /** | |
1981 * @param {string} name | |
1982 * @this {WebInspector.TimelineFilters} | |
1983 */ | |
1984 function categoriesFilterChanged(name) | |
1985 { | |
1986 var categories = WebInspector.TimelineUIUtils.categories(); | |
1987 categories[name].hidden = !categoryFiltersUI[name].checked(); | |
1988 this._notifyFiltersChanged(); | |
1989 } | |
1990 }, | |
1991 | |
1992 _notifyFiltersChanged: function() | |
1993 { | |
1994 this.dispatchEventToListeners(WebInspector.TimelineFilters.Events.Filter
Changed); | |
1995 }, | |
1996 | |
1997 __proto__: WebInspector.Object.prototype | |
1998 }; | |
1999 | |
2000 /** | 1897 /** |
2001 * @constructor | |
2002 * @extends {WebInspector.Object} | |
2003 * @implements {WebInspector.TargetManager.Observer} | 1898 * @implements {WebInspector.TargetManager.Observer} |
| 1899 * @unrestricted |
2004 */ | 1900 */ |
2005 WebInspector.CPUThrottlingManager = function() | 1901 WebInspector.CPUThrottlingManager = class extends WebInspector.Object { |
2006 { | 1902 constructor() { |
| 1903 super(); |
2007 this._targets = []; | 1904 this._targets = []; |
2008 this._throttlingRate = 1.; // No throttling | 1905 this._throttlingRate = 1.; // No throttling |
2009 WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capabili
ty.Browser); | 1906 WebInspector.targetManager.observeTargets(this, WebInspector.Target.Capabili
ty.Browser); |
2010 }; | 1907 } |
2011 | 1908 |
2012 WebInspector.CPUThrottlingManager.prototype = { | 1909 /** |
2013 /** | 1910 * @param {number} value |
2014 * @param {number} value | 1911 */ |
2015 */ | 1912 setRate(value) { |
2016 setRate: function(value) | 1913 this._throttlingRate = value; |
2017 { | 1914 this._targets.forEach(target => target.emulationAgent().setCPUThrottlingRate
(value)); |
2018 this._throttlingRate = value; | 1915 if (value !== 1) |
2019 this._targets.forEach(target => target.emulationAgent().setCPUThrottling
Rate(value)); | 1916 WebInspector.inspectorView.setPanelIcon( |
2020 if (value !== 1) | 1917 'timeline', 'warning-icon', WebInspector.UIString('CPU throttling is e
nabled')); |
2021 WebInspector.inspectorView.setPanelIcon("timeline", "warning-icon",
WebInspector.UIString("CPU throttling is enabled")); | 1918 else |
2022 else | 1919 WebInspector.inspectorView.setPanelIcon('timeline', '', ''); |
2023 WebInspector.inspectorView.setPanelIcon("timeline", "", ""); | 1920 } |
2024 }, | 1921 |
2025 | 1922 /** |
2026 /** | 1923 * @return {number} |
2027 * @return {number} | 1924 */ |
2028 */ | 1925 rate() { |
2029 rate: function() | 1926 return this._throttlingRate; |
2030 { | 1927 } |
2031 return this._throttlingRate; | 1928 |
2032 }, | 1929 /** |
2033 | 1930 * @override |
2034 /** | 1931 * @param {!WebInspector.Target} target |
2035 * @override | 1932 */ |
2036 * @param {!WebInspector.Target} target | 1933 targetAdded(target) { |
2037 */ | 1934 this._targets.push(target); |
2038 targetAdded: function(target) | 1935 target.emulationAgent().setCPUThrottlingRate(this._throttlingRate); |
2039 { | 1936 } |
2040 this._targets.push(target); | 1937 |
2041 target.emulationAgent().setCPUThrottlingRate(this._throttlingRate); | 1938 /** |
2042 }, | 1939 * @override |
2043 | 1940 * @param {!WebInspector.Target} target |
2044 /** | 1941 */ |
2045 * @override | 1942 targetRemoved(target) { |
2046 * @param {!WebInspector.Target} target | 1943 this._targets.remove(target, true); |
2047 */ | 1944 } |
2048 targetRemoved: function(target) | |
2049 { | |
2050 this._targets.remove(target, true); | |
2051 }, | |
2052 | |
2053 __proto__: WebInspector.Object.prototype | |
2054 }; | 1945 }; |
2055 | 1946 |
2056 /** | 1947 /** |
2057 * @constructor | 1948 * @unrestricted |
2058 * @extends {WebInspector.HBox} | |
2059 */ | 1949 */ |
2060 WebInspector.TimelinePanel.CustomCPUThrottlingRateDialog = function() | 1950 WebInspector.TimelinePanel.CustomCPUThrottlingRateDialog = class extends WebInsp
ector.HBox { |
2061 { | 1951 constructor() { |
2062 WebInspector.HBox.call(this, true); | 1952 super(true); |
2063 this.registerRequiredCSS("ui_lazy/dialog.css"); | 1953 this.registerRequiredCSS('ui_lazy/dialog.css'); |
2064 this.contentElement.createChild("label").textContent = WebInspector.UIString
("CPU Slowdown Rate: "); | 1954 this.contentElement.createChild('label').textContent = WebInspector.UIString
('CPU Slowdown Rate: '); |
2065 | 1955 |
2066 this._input = this.contentElement.createChild("input"); | 1956 this._input = this.contentElement.createChild('input'); |
2067 this._input.setAttribute("type", "text"); | 1957 this._input.setAttribute('type', 'text'); |
2068 this._input.style.width = "64px"; | 1958 this._input.style.width = '64px'; |
2069 this._input.addEventListener("keydown", this._onKeyDown.bind(this), false); | 1959 this._input.addEventListener('keydown', this._onKeyDown.bind(this), false); |
2070 | 1960 |
2071 var addButton = this.contentElement.createChild("button"); | 1961 var addButton = this.contentElement.createChild('button'); |
2072 addButton.textContent = WebInspector.UIString("Set"); | 1962 addButton.textContent = WebInspector.UIString('Set'); |
2073 addButton.addEventListener("click", this._apply.bind(this), false); | 1963 addButton.addEventListener('click', this._apply.bind(this), false); |
2074 | 1964 |
2075 this.setDefaultFocusedElement(this._input); | 1965 this.setDefaultFocusedElement(this._input); |
2076 this.contentElement.tabIndex = 0; | 1966 this.contentElement.tabIndex = 0; |
2077 this._resultPromise = new Promise(fulfill => this._callback = fulfill); | 1967 this._resultPromise = new Promise(fulfill => this._callback = fulfill); |
2078 }; | 1968 } |
2079 | 1969 |
2080 /** | 1970 /** |
2081 * @param {!Element=} anchor | 1971 * @param {!Element=} anchor |
2082 * @return {!Promise<string>} | 1972 * @return {!Promise<string>} |
2083 */ | 1973 */ |
2084 WebInspector.TimelinePanel.CustomCPUThrottlingRateDialog.show = function(anchor) | 1974 static show(anchor) { |
2085 { | |
2086 var dialog = new WebInspector.Dialog(); | 1975 var dialog = new WebInspector.Dialog(); |
2087 var dialogContent = new WebInspector.TimelinePanel.CustomCPUThrottlingRateDi
alog(); | 1976 var dialogContent = new WebInspector.TimelinePanel.CustomCPUThrottlingRateDi
alog(); |
2088 dialogContent.show(dialog.element); | 1977 dialogContent.show(dialog.element); |
2089 dialog.setWrapsContent(true); | 1978 dialog.setWrapsContent(true); |
2090 if (anchor) | 1979 if (anchor) |
2091 dialog.setPosition(anchor.totalOffsetLeft() - 32, anchor.totalOffsetTop(
) + anchor.offsetHeight); | 1980 dialog.setPosition(anchor.totalOffsetLeft() - 32, anchor.totalOffsetTop()
+ anchor.offsetHeight); |
2092 dialog.show(); | 1981 dialog.show(); |
2093 return dialogContent.result().then(value => (dialog.detach(), value)); | 1982 return dialogContent.result().then(value => (dialog.detach(), value)); |
2094 }; | 1983 } |
2095 | 1984 |
2096 WebInspector.TimelinePanel.CustomCPUThrottlingRateDialog.prototype = { | 1985 /** |
2097 /** | 1986 * @return {!Promise<string>} |
2098 * @return {!Promise<string>} | 1987 */ |
2099 */ | 1988 result() { |
2100 result: function() | 1989 return this._resultPromise; |
2101 { | 1990 } |
2102 return this._resultPromise; | 1991 |
2103 }, | 1992 _apply() { |
2104 | 1993 this._callback(this._input.value); |
2105 _apply: function() | 1994 } |
2106 { | 1995 |
2107 this._callback(this._input.value); | 1996 /** |
2108 }, | 1997 * @param {!Event} event |
2109 | 1998 */ |
2110 /** | 1999 _onKeyDown(event) { |
2111 * @param {!Event} event | 2000 if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code) { |
2112 */ | 2001 event.preventDefault(); |
2113 _onKeyDown: function(event) | 2002 this._apply(); |
2114 { | 2003 } |
2115 if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code) { | 2004 } |
2116 event.preventDefault(); | 2005 }; |
2117 this._apply(); | 2006 |
2118 } | 2007 |
2119 }, | |
2120 | |
2121 __proto__: WebInspector.HBox.prototype | |
2122 }; | |
OLD | NEW |