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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/network/NetworkLogViewColumns.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4
5 /** 4 /**
6 * @constructor 5 * @unrestricted
7 * @param {!WebInspector.NetworkLogView} networkLogView
8 * @param {!WebInspector.NetworkTransferTimeCalculator} timeCalculator
9 * @param {!WebInspector.NetworkTransferDurationCalculator} durationCalculator
10 * @param {!WebInspector.Setting} networkLogLargeRowsSetting
11 */ 6 */
12 WebInspector.NetworkLogViewColumns = function(networkLogView, timeCalculator, du rationCalculator, networkLogLargeRowsSetting) 7 WebInspector.NetworkLogViewColumns = class {
13 { 8 /**
14 if (Runtime.experiments.isEnabled("canvasNetworkTimeline")) { 9 * @param {!WebInspector.NetworkLogView} networkLogView
15 var timelineColumn = WebInspector.NetworkLogViewColumns._defaultColumns. find(columnConfig => columnConfig.id === "timeline"); 10 * @param {!WebInspector.NetworkTransferTimeCalculator} timeCalculator
16 timelineColumn.visible = false; 11 * @param {!WebInspector.NetworkTransferDurationCalculator} durationCalculator
17 timelineColumn.hideable = false; 12 * @param {!WebInspector.Setting} networkLogLargeRowsSetting
13 */
14 constructor(networkLogView, timeCalculator, durationCalculator, networkLogLarg eRowsSetting) {
15 if (Runtime.experiments.isEnabled('canvasNetworkTimeline')) {
16 var timelineColumn =
17 WebInspector.NetworkLogViewColumns._defaultColumns.find(columnConfig = > columnConfig.id === 'timeline');
18 timelineColumn.visible = false;
19 timelineColumn.hideable = false;
18 } 20 }
19 21
20 this._networkLogView = networkLogView; 22 this._networkLogView = networkLogView;
21 23
22 /** @type {!WebInspector.Setting} */ 24 /** @type {!WebInspector.Setting} */
23 this._persistantSettings = WebInspector.settings.createSetting("networkLogCo lumns", {}); 25 this._persistantSettings = WebInspector.settings.createSetting('networkLogCo lumns', {});
24 26
25 /** @type {!Array<!Element>} */ 27 /** @type {!Array<!Element>} */
26 this._dropDownColumnSelectors = []; 28 this._dropDownColumnSelectors = [];
27 29
28 this._networkLogLargeRowsSetting = networkLogLargeRowsSetting; 30 this._networkLogLargeRowsSetting = networkLogLargeRowsSetting;
29 this._networkLogLargeRowsSetting.addChangeListener(this._updateRowsSize, thi s); 31 this._networkLogLargeRowsSetting.addChangeListener(this._updateRowsSize, thi s);
30 32
31 /** @type {!Array<{time: number, element: !Element}>} */ 33 /** @type {!Array<{time: number, element: !Element}>} */
32 this._eventDividers = []; 34 this._eventDividers = [];
33 35
(...skipping 14 matching lines...) Expand all
48 50
49 /** @type {!WebInspector.Linkifier} */ 51 /** @type {!WebInspector.Linkifier} */
50 this._popupLinkifier = new WebInspector.Linkifier(); 52 this._popupLinkifier = new WebInspector.Linkifier();
51 53
52 /** @type {!Map<string, !WebInspector.NetworkTimeCalculator>} */ 54 /** @type {!Map<string, !WebInspector.NetworkTimeCalculator>} */
53 this._calculatorsMap = new Map(); 55 this._calculatorsMap = new Map();
54 this._calculatorsMap.set(WebInspector.NetworkLogViewColumns._calculatorTypes .Time, timeCalculator); 56 this._calculatorsMap.set(WebInspector.NetworkLogViewColumns._calculatorTypes .Time, timeCalculator);
55 this._calculatorsMap.set(WebInspector.NetworkLogViewColumns._calculatorTypes .Duration, durationCalculator); 57 this._calculatorsMap.set(WebInspector.NetworkLogViewColumns._calculatorTypes .Duration, durationCalculator);
56 58
57 this._setupDataGrid(); 59 this._setupDataGrid();
58 if (Runtime.experiments.isEnabled("canvasNetworkTimeline")) 60 if (Runtime.experiments.isEnabled('canvasNetworkTimeline'))
59 this._setupTimeline(); 61 this._setupTimeline();
62 }
63
64 /**
65 * @param {!WebInspector.NetworkLogViewColumns.Descriptor} columnConfig
66 * @return {!WebInspector.DataGrid.ColumnDescriptor}
67 */
68 static _convertToDataGridDescriptor(columnConfig) {
69 return /** @type {!WebInspector.DataGrid.ColumnDescriptor} */ ({
70 id: columnConfig.id,
71 title: columnConfig.title,
72 sortable: columnConfig.sortable,
73 align: columnConfig.align,
74 nonSelectable: columnConfig.nonSelectable,
75 weight: columnConfig.weight
76 });
77 }
78
79 wasShown() {
80 this._updateRowsSize();
81 }
82
83 willHide() {
84 this._popoverHelper.hidePopover();
85 }
86
87 reset() {
88 if (this._popoverHelper)
89 this._popoverHelper.hidePopover();
90 this._timelineGrid.removeEventDividers();
91 this._shownEventDividers.clear();
92 this.updateDividersIfNeeded();
93 }
94
95 _setupDataGrid() {
96 var defaultColumns = WebInspector.NetworkLogViewColumns._defaultColumns;
97 var defaultColumnConfig = WebInspector.NetworkLogViewColumns._defaultColumnC onfig;
98
99 this._columns = /** @type {!Array<!WebInspector.NetworkLogViewColumns.Descri ptor>} */ ([]);
100 for (var currentConfigColumn of defaultColumns) {
101 var columnConfig = /** @type {!WebInspector.NetworkLogViewColumns.Descript or} */ (
102 Object.assign(/** @type {!Object} */ ({}), defaultColumnConfig, curren tConfigColumn));
103 columnConfig.id = columnConfig.id;
104 if (columnConfig.subtitle)
105 columnConfig.titleDOMFragment = this._makeHeaderFragment(columnConfig.ti tle, columnConfig.subtitle);
106 this._columns.push(columnConfig);
107 }
108 this._loadColumns();
109
110 this._popoverHelper = new WebInspector.PopoverHelper(this._networkLogView.el ement);
111 this._popoverHelper.initializeCallbacks(
112 this._getPopoverAnchor.bind(this), this._showPopover.bind(this), this._o nHidePopover.bind(this));
113
114 this._dataGrid = new WebInspector.SortableDataGrid(
115 this._columns.map(WebInspector.NetworkLogViewColumns._convertToDataGridD escriptor));
116 this._dataGrid.element.addEventListener('mousedown', event => {
117 if ((!this._dataGrid.selectedNode && event.button) || event.target.enclosi ngNodeOrSelfWithNodeName('a'))
118 event.consume();
119 }, true);
120
121 this._dataGridScroller = this._dataGrid.scrollContainer;
122
123 this._updateColumns();
124 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._sortHandler, this);
125 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.ColumnsResized, this.updateDividersIfNeeded, this);
126 this._dataGrid.setHeaderContextMenuCallback(this._innerHeaderContextMenu.bin d(this));
127
128 this._timelineGrid = new WebInspector.TimelineGrid();
129 this._timelineGrid.element.classList.add('network-timeline-grid');
130 if (!Runtime.experiments.isEnabled('canvasNetworkTimeline'))
131 this._dataGrid.element.appendChild(this._timelineGrid.element);
132
133 this._setupDropdownColumns();
134
135 this._activeTimelineSortId = WebInspector.NetworkLogViewColumns.TimelineSort Ids.StartTime;
136 this._dataGrid.markColumnAsSortedBy(
137 WebInspector.NetworkLogViewColumns._initialSortColumn, WebInspector.Data Grid.Order.Ascending);
138
139 if (Runtime.experiments.isEnabled('canvasNetworkTimeline')) {
140 this._splitWidget = new WebInspector.SplitWidget(true, true, 'networkPanel SplitViewTimeline', 200);
141 this._splitWidget.setMainWidget(this._dataGrid.asWidget());
142 }
143 }
144
145 _setupTimeline() {
146 this._timelineColumn =
147 new WebInspector.NetworkTimelineColumn(this._networkLogView.rowHeight(), this._networkLogView.calculator());
148
149 this._timelineColumn.element.addEventListener('contextmenu', handleContextMe nu.bind(this));
150 this._timelineColumn.element.addEventListener('mousewheel', this._onMouseWhe el.bind(this, false), {passive: true});
151 this._dataGridScroller.addEventListener('mousewheel', this._onMouseWheel.bin d(this, true), true);
152
153 this._timelineColumn.element.addEventListener(
154 'mousemove',
155 event => this._networkLogView.setHoveredRequest(
156 this._timelineColumn.getRequestFromPoint(event.offsetX, event.offset Y + event.target.offsetTop),
157 event.shiftKey),
158 true);
159 this._timelineColumn.element.addEventListener(
160 'mouseleave', this._networkLogView.setHoveredRequest.bind(this._networkL ogView, null, false), true);
161
162 this._timelineScroller = this._timelineColumn.contentElement.createChild('di v', 'network-timeline-v-scroll');
163 this._timelineScroller.addEventListener('scroll', this._syncScrollers.bind(t his), {passive: true});
164 this._timelineScrollerContent = this._timelineScroller.createChild('div', 'n etwork-timeline-v-scroll-content');
165
166 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.PaddingChanged, () => {
167 this._timelineScrollerWidthIsStale = true;
168 this._syncScrollers();
169 });
170 this._dataGrid.addEventListener(
171 WebInspector.ViewportDataGrid.Events.ViewportCalculated, this._redrawTim elineColumn.bind(this));
172
173 this._createTimelineHeader();
174 this._timelineColumn.contentElement.classList.add('network-timeline-view');
175
176 this._splitWidget.setSidebarWidget(this._timelineColumn);
177
178 this.switchViewMode(false);
179
180 /**
181 * @param {!Event} event
182 * @this {WebInspector.NetworkLogViewColumns}
183 */
184 function handleContextMenu(event) {
185 var request = this._timelineColumn.getRequestFromPoint(event.offsetX, even t.offsetY);
186 if (!request)
187 return;
188 var contextMenu = new WebInspector.ContextMenu(event);
189 this._networkLogView.handleContextMenuForRequest(contextMenu, request);
190 contextMenu.show();
191 }
192 }
193
194 /**
195 * @param {boolean} shouldConsume
196 * @param {!Event} event
197 */
198 _onMouseWheel(shouldConsume, event) {
199 if (shouldConsume)
200 event.consume(true);
201 this._activeScroller.scrollTop -= event.wheelDeltaY;
202 this._syncScrollers();
203 this._networkLogView.setHoveredRequest(
204 this._timelineColumn.getRequestFromPoint(event.offsetX, event.offsetY), event.shiftKey);
205 }
206
207 _syncScrollers() {
208 if (!this._timelineColumn.isShowing())
209 return;
210 this._timelineScrollerContent.style.height = this._dataGridScroller.scrollHe ight + 'px';
211 this._updateScrollerWidthIfNeeded();
212 this._dataGridScroller.scrollTop = this._timelineScroller.scrollTop;
213 }
214
215 _updateScrollerWidthIfNeeded() {
216 if (this._timelineScrollerWidthIsStale) {
217 this._timelineScrollerWidthIsStale = false;
218 this._timelineColumn.setRightPadding(
219 this._timelineScroller.offsetWidth - this._timelineScrollerContent.off setWidth);
220 }
221 }
222
223 _redrawTimelineColumn() {
224 if (!this._timelineRequestsAreStale) {
225 this._updateScrollerWidthIfNeeded();
226 this._timelineColumn.update(
227 this._activeScroller.scrollTop, this._eventDividersShown ? this._shown EventDividers : undefined);
228 return;
229 }
230 var currentNode = this._dataGrid.rootNode();
231 var requestData = {requests: [], navigationRequest: null};
232 while (currentNode = currentNode.traverseNextNode(true)) {
233 if (currentNode.isNavigationRequest())
234 requestData.navigationRequest = currentNode.request();
235 requestData.requests.push(currentNode.request());
236 }
237 this._timelineColumn.update(this._activeScroller.scrollTop, this._shownEvent Dividers, requestData);
238 }
239
240 /**
241 * @param {?WebInspector.NetworkRequest} request
242 * @param {boolean} highlightInitiatorChain
243 */
244 setHoveredRequest(request, highlightInitiatorChain) {
245 if (Runtime.experiments.isEnabled('canvasNetworkTimeline'))
246 this._timelineColumn.setHoveredRequest(request, highlightInitiatorChain);
247 }
248
249 _createTimelineHeader() {
250 this._timelineHeaderElement = this._timelineColumn.contentElement.createChil d('div', 'network-timeline-header');
251 this._timelineHeaderElement.addEventListener('click', timelineHeaderClicked. bind(this));
252 this._timelineHeaderElement.addEventListener(
253 'contextmenu', event => this._innerHeaderContextMenu(new WebInspector.Co ntextMenu(event)));
254 var innerElement = this._timelineHeaderElement.createChild('div');
255 innerElement.textContent = WebInspector.UIString('Timeline');
256 this._timelineColumnSortIcon = this._timelineHeaderElement.createChild('div' , 'sort-order-icon-container')
257 .createChild('div', 'sort-order-icon');
258
259 /**
260 * @this {WebInspector.NetworkLogViewColumns}
261 */
262 function timelineHeaderClicked() {
263 var sortOrders = WebInspector.DataGrid.Order;
264 var sortOrder =
265 this._dataGrid.sortOrder() === sortOrders.Ascending ? sortOrders.Desce nding : sortOrders.Ascending;
266 this._dataGrid.markColumnAsSortedBy('timeline', sortOrder);
267 this._sortHandler();
268 }
269 }
270
271 /**
272 * @param {!WebInspector.NetworkTimeCalculator} x
273 */
274 setCalculator(x) {
275 if (Runtime.experiments.isEnabled('canvasNetworkTimeline'))
276 this._timelineColumn.setCalculator(x);
277 }
278
279 dataChanged() {
280 if (Runtime.experiments.isEnabled('canvasNetworkTimeline'))
281 this._timelineRequestsAreStale = true;
282 }
283
284 _updateRowsSize() {
285 var largeRows = !!this._networkLogLargeRowsSetting.get();
286 this._dataGrid.element.classList.toggle('small', !largeRows);
287 this._dataGrid.scheduleUpdate();
288
289 if (!Runtime.experiments.isEnabled('canvasNetworkTimeline'))
290 return;
291 this._timelineScrollerWidthIsStale = true;
292 this._timelineColumn.setRowHeight(this._networkLogView.rowHeight());
293 this._timelineScroller.classList.toggle('small', !largeRows);
294 this._timelineHeaderElement.classList.toggle('small', !largeRows);
295 this._timelineGrid.element.classList.toggle('small', !this._networkLogLargeR owsSetting.get());
296 this._timelineColumn.setHeaderHeight(this._timelineScroller.offsetTop);
297 }
298
299 /**
300 * @param {!Element} element
301 */
302 show(element) {
303 if (Runtime.experiments.isEnabled('canvasNetworkTimeline'))
304 this._splitWidget.show(element);
305 else
306 this._dataGrid.asWidget().show(element);
307 }
308
309 /**
310 * @return {!WebInspector.SortableDataGrid} dataGrid
311 */
312 dataGrid() {
313 return this._dataGrid;
314 }
315
316 _setupDropdownColumns() {
317 for (var columnConfig of this._columns) {
318 if (!columnConfig.sortConfig || !columnConfig.sortConfig.entries)
319 continue;
320 var select = createElement('select');
321 var placeHolderOption = select.createChild('option');
322 placeHolderOption.classList.add('hidden');
323 for (var entry of columnConfig.sortConfig.entries) {
324 var option = select.createChild('option');
325 option.value = entry.id;
326 option.label = entry.title;
327 select.appendChild(option);
328 }
329 var header = this._dataGrid.headerTableHeader(columnConfig.id);
330 header.replaceChild(select, header.firstChild);
331 header.createChild('div', 'sort-order-icon-container').createChild('div', 'sort-order-icon');
332 columnConfig.selectBox = select;
333 select.addEventListener('change', this._sortByDropdownItem.bind(this, colu mnConfig), false);
334 this._dropDownColumnSelectors.push(select);
335 }
336 }
337
338 sortByCurrentColumn() {
339 this._sortHandler();
340 }
341
342 _sortHandler() {
343 var columnId = this._dataGrid.sortColumnId();
344 this._networkLogView.removeAllNodeHighlights();
345 if (Runtime.experiments.isEnabled('canvasNetworkTimeline') && columnId === ' timeline') {
346 this._timelineColumnSortIcon.classList.remove('sort-ascending', 'sort-desc ending');
347
348 if (this._dataGrid.sortOrder() === WebInspector.DataGrid.Order.Ascending)
349 this._timelineColumnSortIcon.classList.add('sort-ascending');
350 else
351 this._timelineColumnSortIcon.classList.add('sort-descending');
352
353 this._timelineRequestsAreStale = true;
354 var sortFunction =
355 WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, this._activeTimelineSortId);
356 this._dataGrid.sortNodes(sortFunction, !this._dataGrid.isSortOrderAscendin g());
357 return;
358 }
359
360 var columnConfig = this._columns.find(columnConfig => columnConfig.id === co lumnId);
361 if (!columnConfig)
362 return;
363 if (columnConfig.sortConfig && columnConfig.sortConfig.entries) {
364 this._sortByDropdownItem(columnConfig);
365 return;
366 }
367 if (!columnConfig.sortConfig.sortingFunction)
368 return;
369
370 this._dataGrid.sortNodes(columnConfig.sortConfig.sortingFunction, !this._dat aGrid.isSortOrderAscending());
371 this._networkLogView.dataGridSorted();
372 }
373
374 /**
375 * @param {!WebInspector.NetworkLogViewColumns.Descriptor} columnConfig
376 */
377 _sortByDropdownItem(columnConfig) {
378 this._networkLogView.removeAllNodeHighlights();
379 var selectedIndex = columnConfig.selectBox.selectedIndex;
380 if (!selectedIndex)
381 selectedIndex = 1; // Sort by first item by default.
382 var selectedItemConfig = columnConfig.sortConfig.entries[selectedIndex - 1]; // -1 because of placeholder.
383 var selectedOption = columnConfig.selectBox[selectedIndex];
384 var value = selectedOption.value;
385
386 this._dataGrid.sortNodes(selectedItemConfig.sortingFunction);
387 this._dataGrid.markColumnAsSortedBy(
388 columnConfig.id, /** @type {!WebInspector.DataGrid.Order} */ (selectedIt emConfig.sort));
389 if (selectedItemConfig.calculator)
390 this._networkLogView.setCalculator(this._calculatorsMap.get(selectedItemCo nfig.calculator));
391 columnConfig.selectBox.options[0].label = selectedItemConfig.title;
392 columnConfig.selectBox.selectedIndex = 0;
393 this._networkLogView.dataGridSorted();
394 }
395
396 _updateColumns() {
397 if (!this._dataGrid)
398 return;
399 var visibleColumns = /** @type {!Object.<string, boolean>} */ ({});
400 if (this._gridMode) {
401 for (var columnConfig of this._columns)
402 visibleColumns[columnConfig.id] = columnConfig.visible;
403 } else {
404 visibleColumns.name = true;
405 }
406 this._dataGrid.setColumnsVisiblity(visibleColumns);
407 }
408
409 /**
410 * @param {boolean} gridMode
411 */
412 switchViewMode(gridMode) {
413 if (this._gridMode === gridMode)
414 return;
415 this._gridMode = gridMode;
416
417 if (gridMode) {
418 if (this._dataGrid.selectedNode)
419 this._dataGrid.selectedNode.selected = false;
420 } else {
421 this._networkLogView.removeAllNodeHighlights();
422 this._popoverHelper.hidePopover();
423 }
424
425 this._networkLogView.element.classList.toggle('brief-mode', !gridMode);
426 this._updateColumns();
427
428 if (!Runtime.experiments.isEnabled('canvasNetworkTimeline'))
429 return;
430 // TODO(allada) Move this code into the code above.
431 if (gridMode) {
432 this._splitWidget.showBoth();
433 this._activeScroller = this._timelineScroller;
434 this._timelineScroller.scrollTop = this._dataGridScroller.scrollTop;
435 this._dataGridScroller.style.overflow = 'hidden';
436 this._dataGrid.setScrollContainer(this._timelineScroller);
437 } else {
438 this._splitWidget.hideMain();
439 this._activeScroller = this._dataGridScroller;
440 this._dataGridScroller.style.overflow = 'overlay';
441 this._dataGrid.setScrollContainer(this._dataGridScroller);
442 }
443 }
444
445 /**
446 * @param {!WebInspector.NetworkLogViewColumns.Descriptor} columnConfig
447 */
448 _toggleColumnVisibility(columnConfig) {
449 this._loadColumns();
450 columnConfig.visible = !columnConfig.visible;
451 this._saveColumns();
452 this._updateColumns();
453 }
454
455 _saveColumns() {
456 var saveableSettings = {};
457 for (var columnConfig of this._columns) {
458 saveableSettings[columnConfig.id] = {visible: columnConfig.visible, title: columnConfig.title};
459 }
460 this._persistantSettings.set(saveableSettings);
461 }
462
463 _loadColumns() {
464 var savedSettings = this._persistantSettings.get();
465 var columnIds = Object.keys(savedSettings);
466 for (var columnId of columnIds) {
467 var setting = savedSettings[columnId];
468 var columnConfig = this._columns.find(columnConfig => columnConfig.id === columnId);
469 if (!columnConfig)
470 columnConfig = this._addCustomHeader(setting.title, columnId);
471 if (columnConfig.hideable && typeof setting.visible === 'boolean')
472 columnConfig.visible = !!setting.visible;
473 if (typeof setting.title === 'string')
474 columnConfig.title = setting.title;
475 }
476 }
477
478 /**
479 * @param {string} title
480 * @param {string} subtitle
481 * @return {!DocumentFragment}
482 */
483 _makeHeaderFragment(title, subtitle) {
484 var fragment = createDocumentFragment();
485 fragment.createTextChild(title);
486 var subtitleDiv = fragment.createChild('div', 'network-header-subtitle');
487 subtitleDiv.createTextChild(subtitle);
488 return fragment;
489 }
490
491 /**
492 * @param {!WebInspector.ContextMenu} contextMenu
493 */
494 _innerHeaderContextMenu(contextMenu) {
495 if (Runtime.experiments.isEnabled('canvasNetworkTimeline')) {
496 var timelineSortIds = WebInspector.NetworkLogViewColumns.TimelineSortIds;
497 var timelineSubMenu = contextMenu.appendSubMenuItem(WebInspector.UIString( 'Timeline'));
498 timelineSubMenu.appendCheckboxItem(
499 WebInspector.UIString('Start Time'), setTimelineMode.bind(this, timeli neSortIds.StartTime),
500 this._activeTimelineSortId === timelineSortIds.StartTime);
501 timelineSubMenu.appendCheckboxItem(
502 WebInspector.UIString('Response Time'), setTimelineMode.bind(this, tim elineSortIds.ResponseTime),
503 this._activeTimelineSortId === timelineSortIds.ResponseTime);
504 timelineSubMenu.appendCheckboxItem(
505 WebInspector.UIString('End Time'), setTimelineMode.bind(this, timeline SortIds.EndTime),
506 this._activeTimelineSortId === timelineSortIds.EndTime);
507 timelineSubMenu.appendCheckboxItem(
508 WebInspector.UIString('Total Duration'), setTimelineMode.bind(this, ti melineSortIds.Duration),
509 this._activeTimelineSortId === timelineSortIds.Duration);
510 timelineSubMenu.appendCheckboxItem(
511 WebInspector.UIString('Latency'), setTimelineMode.bind(this, timelineS ortIds.Latency),
512 this._activeTimelineSortId === timelineSortIds.Latency);
513 contextMenu.appendSeparator();
514 }
515 var columnConfigs = this._columns.filter(columnConfig => columnConfig.hideab le);
516 var nonResponseHeaders = columnConfigs.filter(columnConfig => !columnConfig. isResponseHeader);
517 for (var columnConfig of nonResponseHeaders)
518 contextMenu.appendCheckboxItem(
519 columnConfig.title, this._toggleColumnVisibility.bind(this, columnConf ig), columnConfig.visible);
520
521 contextMenu.appendSeparator();
522
523 var responseSubMenu = contextMenu.appendSubMenuItem(WebInspector.UIString('R esponse Headers'));
524 var responseHeaders = columnConfigs.filter(columnConfig => columnConfig.isRe sponseHeader);
525 for (var columnConfig of responseHeaders)
526 responseSubMenu.appendCheckboxItem(
527 columnConfig.title, this._toggleColumnVisibility.bind(this, columnConf ig), columnConfig.visible);
528
529 responseSubMenu.appendSeparator();
530 responseSubMenu.appendItem(
531 WebInspector.UIString('Manage Header Columns\u2026'), this._manageCustom HeaderDialog.bind(this));
532
533 contextMenu.show();
534
535 /**
536 * @param {!WebInspector.NetworkLogViewColumns.TimelineSortIds} sortId
537 * @this {WebInspector.NetworkLogViewColumns}
538 */
539 function setTimelineMode(sortId) {
540 var calculator = this._calculatorsMap.get(WebInspector.NetworkLogViewColum ns._calculatorTypes.Time);
541 var timelineSortIds = WebInspector.NetworkLogViewColumns.TimelineSortIds;
542 if (sortId === timelineSortIds.Duration || sortId === timelineSortIds.Late ncy)
543 calculator = this._calculatorsMap.get(WebInspector.NetworkLogViewColumns ._calculatorTypes.Duration);
544 this._networkLogView.setCalculator(calculator);
545
546 this._activeTimelineSortId = sortId;
547 this._dataGrid.markColumnAsSortedBy('timeline', WebInspector.DataGrid.Orde r.Ascending);
548 this._sortHandler();
549 }
550 }
551
552 _manageCustomHeaderDialog() {
553 var customHeaders = [];
554 for (var columnConfig of this._columns) {
555 if (columnConfig.isResponseHeader)
556 customHeaders.push({title: columnConfig.title, editable: columnConfig.is CustomHeader});
557 }
558 var manageCustomHeaders = new WebInspector.NetworkManageCustomHeadersView(
559 customHeaders, headerTitle => !!this._addCustomHeader(headerTitle), this ._changeCustomHeader.bind(this),
560 this._removeCustomHeader.bind(this));
561 var dialog = new WebInspector.Dialog();
562 manageCustomHeaders.show(dialog.element);
563 dialog.setWrapsContent(true);
564 dialog.show();
565 }
566
567 /**
568 * @param {string} headerId
569 * @return {boolean}
570 */
571 _removeCustomHeader(headerId) {
572 headerId = headerId.toLowerCase();
573 var index = this._columns.findIndex(columnConfig => columnConfig.id === head erId);
574 if (index === -1)
575 return false;
576 var columnConfig = this._columns.splice(index, 1);
577 this._dataGrid.removeColumn(headerId);
578 this._saveColumns();
579 this._updateColumns();
580 return true;
581 }
582
583 /**
584 * @param {string} headerTitle
585 * @param {string=} headerId
586 * @param {number=} index
587 * @return {?WebInspector.NetworkLogViewColumns.Descriptor}
588 */
589 _addCustomHeader(headerTitle, headerId, index) {
590 if (!headerId)
591 headerId = headerTitle.toLowerCase();
592 if (index === undefined)
593 index = this._columns.length - 1;
594
595 var currentColumnConfig = this._columns.find(columnConfig => columnConfig.id === headerId);
596 if (currentColumnConfig)
597 return null;
598
599 var columnConfig = /** @type {!WebInspector.NetworkLogViewColumns.Descriptor } */ (
600 Object.assign(/** @type {!Object} */ ({}), WebInspector.NetworkLogViewCo lumns._defaultColumnConfig, {
601 id: headerId,
602 title: headerTitle,
603 isResponseHeader: true,
604 isCustomHeader: true,
605 visible: true,
606 sortConfig: {
607 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStri ngComparator.bind(null, headerId)
608 }
609 }));
610 this._columns.splice(index, 0, columnConfig);
611 if (this._dataGrid)
612 this._dataGrid.addColumn(WebInspector.NetworkLogViewColumns._convertToData GridDescriptor(columnConfig), index);
613 this._saveColumns();
614 this._updateColumns();
615 return columnConfig;
616 }
617
618 /**
619 * @param {string} oldHeaderId
620 * @param {string} newHeaderTitle
621 * @param {string=} newHeaderId
622 * @return {boolean}
623 */
624 _changeCustomHeader(oldHeaderId, newHeaderTitle, newHeaderId) {
625 if (!newHeaderId)
626 newHeaderId = newHeaderTitle.toLowerCase();
627 oldHeaderId = oldHeaderId.toLowerCase();
628
629 var oldIndex = this._columns.findIndex(columnConfig => columnConfig.id === o ldHeaderId);
630 var oldColumnConfig = this._columns[oldIndex];
631 var currentColumnConfig = this._columns.find(columnConfig => columnConfig.id === newHeaderId);
632 if (!oldColumnConfig || (currentColumnConfig && oldHeaderId !== newHeaderId) )
633 return false;
634
635 this._removeCustomHeader(oldHeaderId);
636 this._addCustomHeader(newHeaderTitle, newHeaderId, oldIndex);
637 return true;
638 }
639
640 updateDividersIfNeeded() {
641 // TODO(allada) Remove this code out when timeline canvas experiment is over .
642 if (Runtime.experiments.isEnabled('canvasNetworkTimeline'))
643 return;
644 if (!this._networkLogView.isShowing()) {
645 this._networkLogView.scheduleRefresh();
646 return;
647 }
648
649 var timelineOffset = this._dataGrid.columnOffset('timeline');
650 // Position timline grid location.
651 if (timelineOffset)
652 this._timelineGrid.element.style.left = timelineOffset + 'px';
653
654 var calculator = this._calculatorsMap.get(WebInspector.NetworkLogViewColumns ._calculatorTypes.Time);
655 calculator.setDisplayWindow(this._timelineGrid.dividersElement.clientWidth);
656 this._timelineGrid.updateDividers(calculator, 75);
657
658 if (calculator.startAtZero) {
659 // If our current sorting method starts at zero, that means it shows all
660 // requests starting at the same point, and so onLoad event and DOMContent
661 // event lines really wouldn't make much sense here, so don't render them.
662 return;
663 }
664
665 this._updateEventDividers();
666 }
667
668 /**
669 * @param {!Element} element
670 * @param {!Event} event
671 * @return {!Element|!AnchorBox|undefined}
672 */
673 _getPopoverAnchor(element, event) {
674 if (!this._gridMode)
675 return;
676 var anchor = element.enclosingNodeOrSelfWithClass('network-graph-bar') ||
677 element.enclosingNodeOrSelfWithClass('network-graph-label');
678 if (anchor && anchor.parentElement.request && anchor.parentElement.request.t iming)
679 return anchor;
680 anchor = element.enclosingNodeOrSelfWithClass('network-script-initiated');
681 if (anchor && anchor.request) {
682 var initiator = /** @type {!WebInspector.NetworkRequest} */ (anchor.reques t).initiator();
683 if (initiator && initiator.stack)
684 return anchor;
685 }
686 }
687
688 /**
689 * @param {!Element} anchor
690 * @param {!WebInspector.Popover} popover
691 */
692 _showPopover(anchor, popover) {
693 var content;
694 if (anchor.classList.contains('network-script-initiated')) {
695 var request = /** @type {!WebInspector.NetworkRequest} */ (anchor.request) ;
696 var initiator = /** @type {!NetworkAgent.Initiator} */ (request.initiator( ));
697 content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents (
698 request.target(), this._popupLinkifier, initiator.stack);
699 popover.setCanShrink(true);
700 } else {
701 content = WebInspector.RequestTimingView.createTimingTable(
702 anchor.parentElement.request, this._networkLogView.timeCalculator().mi nimumBoundary());
703 popover.setCanShrink(false);
704 }
705 popover.showForAnchor(content, anchor);
706 }
707
708 _onHidePopover() {
709 this._popupLinkifier.reset();
710 }
711
712 /**
713 * @param {!Array<number>} times
714 * @param {string} className
715 */
716 addEventDividers(times, className) {
717 if (Runtime.experiments.isEnabled('canvasNetworkTimeline')) {
718 // TODO(allada) When we remove old timeline remove this and pass in the co lor.
719 var color = 'transparent';
720 switch (className) {
721 case 'network-blue-divider':
722 color = 'hsla(240, 100%, 80%, 0.7)';
723 break;
724 case 'network-red-divider':
725 color = 'rgba(255, 0, 0, 0.5)';
726 break;
727 default:
728 return;
729 }
730 var currentTimes = this._shownEventDividers.get(color) || [];
731 this._shownEventDividers.set(color, currentTimes.concat(times));
732
733 this._networkLogView.scheduleRefresh();
734 return;
735 }
736
737 for (var i = 0; i < times.length; ++i) {
738 var element = createElementWithClass('div', 'network-event-divider ' + cla ssName);
739 this._timelineGrid.addEventDivider(element);
740 this._eventDividers.push({time: times[i], element: element});
741 }
742 // Update event dividers immediately
743 this._updateEventDividers();
744 // Schedule refresh in case dividers change the calculator span.
745 this._networkLogView.scheduleRefresh();
746 }
747
748 _updateEventDividers() {
749 if (Runtime.experiments.isEnabled('canvasNetworkTimeline'))
750 return;
751 var calculator = this._calculatorsMap.get(WebInspector.NetworkLogViewColumns ._calculatorTypes.Time);
752 for (var divider of this._eventDividers) {
753 var timePercent = calculator.computePercentageFromEventTime(divider.time);
754 divider.element.classList.toggle('invisible', timePercent < 0);
755 divider.element.style.left = timePercent + '%';
756 }
757 }
758
759 hideEventDividers() {
760 this._eventDividersShown = true;
761 if (Runtime.experiments.isEnabled('canvasNetworkTimeline')) {
762 this._redrawTimelineColumn();
763 return;
764 }
765 this._timelineGrid.hideEventDividers();
766 }
767
768 showEventDividers() {
769 this._eventDividersShown = false;
770 if (Runtime.experiments.isEnabled('canvasNetworkTimeline')) {
771 this._redrawTimelineColumn();
772 return;
773 }
774 this._timelineGrid.showEventDividers();
775 }
776
777 /**
778 * @param {number} time
779 */
780 selectFilmStripFrame(time) {
781 if (Runtime.experiments.isEnabled('canvasNetworkTimeline')) {
782 this._shownEventDividers.set(WebInspector.NetworkLogViewColumns._filmStrip DividerColor, [time]);
783 this._redrawTimelineColumn();
784 return;
785 }
786 for (var divider of this._eventDividers)
787 divider.element.classList.toggle('network-frame-divider-selected', divider .time === time);
788 }
789
790 clearFilmStripFrame() {
791 if (Runtime.experiments.isEnabled('canvasNetworkTimeline')) {
792 this._shownEventDividers.delete(WebInspector.NetworkLogViewColumns._filmSt ripDividerColor);
793 this._redrawTimelineColumn();
794 return;
795 }
796 for (var divider of this._eventDividers)
797 divider.element.classList.toggle('network-frame-divider-selected', false);
798 }
60 }; 799 };
61 800
62 WebInspector.NetworkLogViewColumns._initialSortColumn = "timeline"; 801 WebInspector.NetworkLogViewColumns._initialSortColumn = 'timeline';
63 802
64 /** 803 /**
65 * @typedef {{ 804 * @typedef {{
66 * id: string, 805 * id: string,
67 * title: string, 806 * title: string,
68 * titleDOMFragment: (!DocumentFragment|undefined), 807 * titleDOMFragment: (!DocumentFragment|undefined),
69 * subtitle: (string|null), 808 * subtitle: (string|null),
70 * visible: boolean, 809 * visible: boolean,
71 * weight: number, 810 * weight: number,
72 * hideable: boolean, 811 * hideable: boolean,
(...skipping 10 matching lines...) Expand all
83 /** 822 /**
84 * @typedef {{ 823 * @typedef {{
85 * sortingFunction: (!function(!WebInspector.NetworkDataGridNode, !WebInspec tor.NetworkDataGridNode):number|undefined), 824 * sortingFunction: (!function(!WebInspector.NetworkDataGridNode, !WebInspec tor.NetworkDataGridNode):number|undefined),
86 * entries: (!Array.<!WebInspector.DataGrid.ColumnDescriptor>|undefined) 825 * entries: (!Array.<!WebInspector.DataGrid.ColumnDescriptor>|undefined)
87 * }} 826 * }}
88 */ 827 */
89 WebInspector.NetworkLogViewColumns.SortConfig; 828 WebInspector.NetworkLogViewColumns.SortConfig;
90 829
91 /** @enum {string} */ 830 /** @enum {string} */
92 WebInspector.NetworkLogViewColumns._calculatorTypes = { 831 WebInspector.NetworkLogViewColumns._calculatorTypes = {
93 Duration: "Duration", 832 Duration: 'Duration',
94 Time: "Time" 833 Time: 'Time'
95 }; 834 };
96 835
97 /** 836 /**
98 * @type {!Object} column 837 * @type {!Object} column
99 */ 838 */
100 WebInspector.NetworkLogViewColumns._defaultColumnConfig = { 839 WebInspector.NetworkLogViewColumns._defaultColumnConfig = {
101 subtitle: null, 840 subtitle: null,
102 visible: false, 841 visible: false,
103 weight: 6, 842 weight: 6,
104 sortable: true, 843 sortable: true,
105 hideable: true, 844 hideable: true,
106 nonSelectable: true, 845 nonSelectable: true,
107 isResponseHeader: false, 846 isResponseHeader: false,
108 alwaysVisible: false, 847 alwaysVisible: false,
109 isCustomHeader: false 848 isCustomHeader: false
110 }; 849 };
111 850
112 /** 851 /**
113 * @type {!Array.<!WebInspector.NetworkLogViewColumns.Descriptor>} column 852 * @type {!Array.<!WebInspector.NetworkLogViewColumns.Descriptor>} column
114 */ 853 */
115 WebInspector.NetworkLogViewColumns._defaultColumns = [ 854 WebInspector.NetworkLogViewColumns._defaultColumns = [
116 { 855 {
117 id: "name", 856 id: 'name',
118 title: WebInspector.UIString("Name"), 857 title: WebInspector.UIString('Name'),
119 subtitle: WebInspector.UIString("Path"), 858 subtitle: WebInspector.UIString('Path'),
120 visible: true, 859 visible: true,
121 weight: 20, 860 weight: 20,
122 hideable: false, 861 hideable: false,
123 nonSelectable: false, 862 nonSelectable: false,
124 alwaysVisible: true, 863 alwaysVisible: true,
125 sortConfig: { 864 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.NameComparato r}
126 sortingFunction: WebInspector.NetworkDataGridNode.NameComparator 865 },
866 {
867 id: 'method',
868 title: WebInspector.UIString('Method'),
869 sortConfig:
870 {sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCompar ator.bind(null, 'requestMethod')}
871 },
872 {
873 id: 'status',
874 title: WebInspector.UIString('Status'),
875 visible: true,
876 subtitle: WebInspector.UIString('Text'),
877 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.RequestProper tyComparator.bind(null, 'statusCode')}
878 },
879 {
880 id: 'protocol',
881 title: WebInspector.UIString('Protocol'),
882 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.RequestProper tyComparator.bind(null, 'protocol')}
883 },
884 {
885 id: 'scheme',
886 title: WebInspector.UIString('Scheme'),
887 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.RequestProper tyComparator.bind(null, 'scheme')}
888 },
889 {
890 id: 'domain',
891 title: WebInspector.UIString('Domain'),
892 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.RequestProper tyComparator.bind(null, 'domain')}
893 },
894 {
895 id: 'remoteaddress',
896 title: WebInspector.UIString('Remote Address'),
897 weight: 10,
898 align: WebInspector.DataGrid.Align.Right,
899 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.RemoteAddress Comparator}
900 },
901 {
902 id: 'type',
903 title: WebInspector.UIString('Type'),
904 visible: true,
905 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.TypeComparato r}
906 },
907 {
908 id: 'initiator',
909 title: WebInspector.UIString('Initiator'),
910 visible: true,
911 weight: 10,
912 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.InitiatorComp arator}
913 },
914 {
915 id: 'cookies',
916 title: WebInspector.UIString('Cookies'),
917 align: WebInspector.DataGrid.Align.Right,
918 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.RequestCookie sCountComparator}
919 },
920 {
921 id: 'setcookies',
922 title: WebInspector.UIString('Set Cookies'),
923 align: WebInspector.DataGrid.Align.Right,
924 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.ResponseCooki esCountComparator}
925 },
926 {
927 id: 'size',
928 title: WebInspector.UIString('Size'),
929 visible: true,
930 subtitle: WebInspector.UIString('Content'),
931 align: WebInspector.DataGrid.Align.Right,
932 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.SizeComparato r}
933 },
934 {
935 id: 'time',
936 title: WebInspector.UIString('Time'),
937 visible: true,
938 subtitle: WebInspector.UIString('Latency'),
939 align: WebInspector.DataGrid.Align.Right,
940 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.RequestProper tyComparator.bind(null, 'duration')}
941 },
942 {
943 id: 'priority',
944 title: WebInspector.UIString('Priority'),
945 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.InitialPriori tyComparator}
946 },
947 {
948 id: 'connectionid',
949 title: WebInspector.UIString('Connection ID'),
950 sortConfig:
951 {sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCompar ator.bind(null, 'connectionId')}
952 },
953 {
954 id: 'cache-control',
955 isResponseHeader: true,
956 title: WebInspector.UIString('Cache-Control'),
957 sortConfig:
958 {sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStringC omparator.bind(null, 'cache-control')}
959 },
960 {
961 id: 'connection',
962 isResponseHeader: true,
963 title: WebInspector.UIString('Connection'),
964 sortConfig:
965 {sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStringC omparator.bind(null, 'connection')}
966 },
967 {
968 id: 'content-encoding',
969 isResponseHeader: true,
970 title: WebInspector.UIString('Content-Encoding'),
971 sortConfig: {
972 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStringComp arator.bind(null, 'content-encoding')
973 }
974 },
975 {
976 id: 'content-length',
977 isResponseHeader: true,
978 title: WebInspector.UIString('Content-Length'),
979 align: WebInspector.DataGrid.Align.Right,
980 sortConfig: {
981 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderNumberComp arator.bind(null, 'content-length')
982 }
983 },
984 {
985 id: 'etag',
986 isResponseHeader: true,
987 title: WebInspector.UIString('ETag'),
988 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeade rStringComparator.bind(null, 'etag')}
989 },
990 {
991 id: 'keep-alive',
992 isResponseHeader: true,
993 title: WebInspector.UIString('Keep-Alive'),
994 sortConfig:
995 {sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStringC omparator.bind(null, 'keep-alive')}
996 },
997 {
998 id: 'last-modified',
999 isResponseHeader: true,
1000 title: WebInspector.UIString('Last-Modified'),
1001 sortConfig:
1002 {sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderDateCom parator.bind(null, 'last-modified')}
1003 },
1004 {
1005 id: 'server',
1006 isResponseHeader: true,
1007 title: WebInspector.UIString('Server'),
1008 sortConfig:
1009 {sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStringC omparator.bind(null, 'server')}
1010 },
1011 {
1012 id: 'vary',
1013 isResponseHeader: true,
1014 title: WebInspector.UIString('Vary'),
1015 sortConfig: {sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeade rStringComparator.bind(null, 'vary')}
1016 },
1017 {
1018 id: 'timeline',
1019 title: WebInspector.UIString('Timeline'),
1020 visible: true,
1021 weight: 40,
1022 sortable: false,
1023 hideable: false,
1024 sortConfig: {
1025 entries: [
1026 {
1027 id: 'starttime',
1028 title: WebInspector.UIString('Timeline \u2013 Start Time'),
1029 sort: WebInspector.DataGrid.Order.Ascending,
1030 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCompa rator.bind(null, 'startTime'),
1031 calculator: WebInspector.NetworkLogViewColumns._calculatorTypes.Time
1032 },
1033 {
1034 id: 'responsetime',
1035 title: WebInspector.UIString('Timeline \u2013 Response Time'),
1036 sort: WebInspector.DataGrid.Order.Ascending,
1037 sortingFunction:
1038 WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(nu ll, 'responseReceivedTime'),
1039 calculator: WebInspector.NetworkLogViewColumns._calculatorTypes.Time
1040 },
1041 {
1042 id: 'endtime',
1043 title: WebInspector.UIString('Timeline \u2013 End Time'),
1044 sort: WebInspector.DataGrid.Order.Ascending,
1045 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCompa rator.bind(null, 'endTime'),
1046 calculator: WebInspector.NetworkLogViewColumns._calculatorTypes.Time
1047 },
1048 {
1049 id: 'duration',
1050 title: WebInspector.UIString('Timeline \u2013 Total Duration'),
1051 sort: WebInspector.DataGrid.Order.Descending,
1052 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCompa rator.bind(null, 'duration'),
1053 calculator: WebInspector.NetworkLogViewColumns._calculatorTypes.Durati on
1054 },
1055 {
1056 id: 'latency',
1057 title: WebInspector.UIString('Timeline \u2013 Latency'),
1058 sort: WebInspector.DataGrid.Order.Descending,
1059 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCompa rator.bind(null, 'latency'),
1060 calculator: WebInspector.NetworkLogViewColumns._calculatorTypes.Durati on
127 } 1061 }
128 }, 1062 ]
129 {
130 id: "method",
131 title: WebInspector.UIString("Method"),
132 sortConfig: {
133 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCom parator.bind(null, "requestMethod")
134 }
135 },
136 {
137 id: "status",
138 title: WebInspector.UIString("Status"),
139 visible: true,
140 subtitle: WebInspector.UIString("Text"),
141 sortConfig: {
142 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCom parator.bind(null, "statusCode")
143 }
144 },
145 {
146 id: "protocol",
147 title: WebInspector.UIString("Protocol"),
148 sortConfig: {
149 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCom parator.bind(null, "protocol")
150 }
151 },
152 {
153 id: "scheme",
154 title: WebInspector.UIString("Scheme"),
155 sortConfig: {
156 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCom parator.bind(null, "scheme")
157 }
158 },
159 {
160 id: "domain",
161 title: WebInspector.UIString("Domain"),
162 sortConfig: {
163 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCom parator.bind(null, "domain")
164 }
165 },
166 {
167 id: "remoteaddress",
168 title: WebInspector.UIString("Remote Address"),
169 weight: 10,
170 align: WebInspector.DataGrid.Align.Right,
171 sortConfig: {
172 sortingFunction: WebInspector.NetworkDataGridNode.RemoteAddressCompa rator
173 }
174 },
175 {
176 id: "type",
177 title: WebInspector.UIString("Type"),
178 visible: true,
179 sortConfig: {
180 sortingFunction: WebInspector.NetworkDataGridNode.TypeComparator
181 }
182 },
183 {
184 id: "initiator",
185 title: WebInspector.UIString("Initiator"),
186 visible: true,
187 weight: 10,
188 sortConfig: {
189 sortingFunction: WebInspector.NetworkDataGridNode.InitiatorComparato r
190 }
191 },
192 {
193 id: "cookies",
194 title: WebInspector.UIString("Cookies"),
195 align: WebInspector.DataGrid.Align.Right,
196 sortConfig: {
197 sortingFunction: WebInspector.NetworkDataGridNode.RequestCookiesCoun tComparator
198 }
199 },
200 {
201 id: "setcookies",
202 title: WebInspector.UIString("Set Cookies"),
203 align: WebInspector.DataGrid.Align.Right,
204 sortConfig: {
205 sortingFunction: WebInspector.NetworkDataGridNode.ResponseCookiesCou ntComparator
206 }
207 },
208 {
209 id: "size",
210 title: WebInspector.UIString("Size"),
211 visible: true,
212 subtitle: WebInspector.UIString("Content"),
213 align: WebInspector.DataGrid.Align.Right,
214 sortConfig: {
215 sortingFunction: WebInspector.NetworkDataGridNode.SizeComparator
216 }
217 },
218 {
219 id: "time",
220 title: WebInspector.UIString("Time"),
221 visible: true,
222 subtitle: WebInspector.UIString("Latency"),
223 align: WebInspector.DataGrid.Align.Right,
224 sortConfig: {
225 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCom parator.bind(null, "duration")
226 }
227 },
228 {
229 id: "priority",
230 title: WebInspector.UIString("Priority"),
231 sortConfig: {
232 sortingFunction: WebInspector.NetworkDataGridNode.InitialPriorityCom parator
233 }
234 },
235 {
236 id: "connectionid",
237 title: WebInspector.UIString("Connection ID"),
238 sortConfig: {
239 sortingFunction: WebInspector.NetworkDataGridNode.RequestPropertyCom parator.bind(null, "connectionId")
240 }
241 },
242 {
243 id: "cache-control",
244 isResponseHeader: true,
245 title: WebInspector.UIString("Cache-Control"),
246 sortConfig: {
247 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStri ngComparator.bind(null, "cache-control")
248 }
249 },
250 {
251 id: "connection",
252 isResponseHeader: true,
253 title: WebInspector.UIString("Connection"),
254 sortConfig: {
255 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStri ngComparator.bind(null, "connection")
256 }
257 },
258 {
259 id: "content-encoding",
260 isResponseHeader: true,
261 title: WebInspector.UIString("Content-Encoding"),
262 sortConfig: {
263 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStri ngComparator.bind(null, "content-encoding")
264 }
265 },
266 {
267 id: "content-length",
268 isResponseHeader: true,
269 title: WebInspector.UIString("Content-Length"),
270 align: WebInspector.DataGrid.Align.Right,
271 sortConfig: {
272 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderNumb erComparator.bind(null, "content-length")
273 }
274 },
275 {
276 id: "etag",
277 isResponseHeader: true,
278 title: WebInspector.UIString("ETag"),
279 sortConfig: {
280 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStri ngComparator.bind(null, "etag")
281 }
282 },
283 {
284 id: "keep-alive",
285 isResponseHeader: true,
286 title: WebInspector.UIString("Keep-Alive"),
287 sortConfig: {
288 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStri ngComparator.bind(null, "keep-alive")
289 }
290 },
291 {
292 id: "last-modified",
293 isResponseHeader: true,
294 title: WebInspector.UIString("Last-Modified"),
295 sortConfig: {
296 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderDate Comparator.bind(null, "last-modified")
297 }
298 },
299 {
300 id: "server",
301 isResponseHeader: true,
302 title: WebInspector.UIString("Server"),
303 sortConfig: {
304 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStri ngComparator.bind(null, "server")
305 }
306 },
307 {
308 id: "vary",
309 isResponseHeader: true,
310 title: WebInspector.UIString("Vary"),
311 sortConfig: {
312 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeaderStri ngComparator.bind(null, "vary")
313 }
314 },
315 {
316 id: "timeline",
317 title: WebInspector.UIString("Timeline"),
318 visible: true,
319 weight: 40,
320 sortable: false,
321 hideable: false,
322 sortConfig: {
323 entries: [
324 {
325 id: "starttime",
326 title: WebInspector.UIString("Timeline \u2013 Start Time"),
327 sort: WebInspector.DataGrid.Order.Ascending,
328 sortingFunction: WebInspector.NetworkDataGridNode.RequestPro pertyComparator.bind(null, "startTime"),
329 calculator: WebInspector.NetworkLogViewColumns._calculatorTy pes.Time
330 },
331 {
332 id: "responsetime",
333 title: WebInspector.UIString("Timeline \u2013 Response Time" ),
334 sort: WebInspector.DataGrid.Order.Ascending,
335 sortingFunction: WebInspector.NetworkDataGridNode.RequestPro pertyComparator.bind(null, "responseReceivedTime"),
336 calculator: WebInspector.NetworkLogViewColumns._calculatorTy pes.Time
337 },
338 {
339 id: "endtime",
340 title: WebInspector.UIString("Timeline \u2013 End Time"),
341 sort: WebInspector.DataGrid.Order.Ascending,
342 sortingFunction: WebInspector.NetworkDataGridNode.RequestPro pertyComparator.bind(null, "endTime"),
343 calculator: WebInspector.NetworkLogViewColumns._calculatorTy pes.Time
344 },
345 {
346 id: "duration",
347 title: WebInspector.UIString("Timeline \u2013 Total Duration "),
348 sort: WebInspector.DataGrid.Order.Descending,
349 sortingFunction: WebInspector.NetworkDataGridNode.RequestPro pertyComparator.bind(null, "duration"),
350 calculator: WebInspector.NetworkLogViewColumns._calculatorTy pes.Duration
351 },
352 {
353 id: "latency",
354 title: WebInspector.UIString("Timeline \u2013 Latency"),
355 sort: WebInspector.DataGrid.Order.Descending,
356 sortingFunction: WebInspector.NetworkDataGridNode.RequestPro pertyComparator.bind(null, "latency"),
357 calculator: WebInspector.NetworkLogViewColumns._calculatorTy pes.Duration
358 }
359 ]
360 }
361 } 1063 }
1064 }
362 ]; 1065 ];
363 1066
364 WebInspector.NetworkLogViewColumns._filmStripDividerColor = "#fccc49"; 1067 WebInspector.NetworkLogViewColumns._filmStripDividerColor = '#fccc49';
365 1068
366 /** 1069 /**
367 * @enum {string} 1070 * @enum {string}
368 */ 1071 */
369 WebInspector.NetworkLogViewColumns.TimelineSortIds = { 1072 WebInspector.NetworkLogViewColumns.TimelineSortIds = {
370 StartTime: "startTime", 1073 StartTime: 'startTime',
371 ResponseTime: "responseReceivedTime", 1074 ResponseTime: 'responseReceivedTime',
372 EndTime: "endTime", 1075 EndTime: 'endTime',
373 Duration: "duration", 1076 Duration: 'duration',
374 Latency: "latency" 1077 Latency: 'latency'
375 }; 1078 };
376 1079
377 /** 1080
378 * @param {!WebInspector.NetworkLogViewColumns.Descriptor} columnConfig
379 * @return {!WebInspector.DataGrid.ColumnDescriptor}
380 */
381 WebInspector.NetworkLogViewColumns._convertToDataGridDescriptor = function(colum nConfig)
382 {
383 return /** @type {!WebInspector.DataGrid.ColumnDescriptor} */ ({
384 id: columnConfig.id,
385 title: columnConfig.title,
386 sortable: columnConfig.sortable,
387 align: columnConfig.align,
388 nonSelectable: columnConfig.nonSelectable,
389 weight: columnConfig.weight
390 });
391 };
392
393 WebInspector.NetworkLogViewColumns.prototype = {
394 wasShown: function()
395 {
396 this._updateRowsSize();
397 },
398
399 willHide: function()
400 {
401 this._popoverHelper.hidePopover();
402 },
403
404 reset: function()
405 {
406 if (this._popoverHelper)
407 this._popoverHelper.hidePopover();
408 this._timelineGrid.removeEventDividers();
409 this._shownEventDividers.clear();
410 this.updateDividersIfNeeded();
411 },
412
413 _setupDataGrid: function()
414 {
415 var defaultColumns = WebInspector.NetworkLogViewColumns._defaultColumns;
416 var defaultColumnConfig = WebInspector.NetworkLogViewColumns._defaultCol umnConfig;
417
418 this._columns = /** @type {!Array<!WebInspector.NetworkLogViewColumns.De scriptor>} */ ([]);
419 for (var currentConfigColumn of defaultColumns) {
420 var columnConfig = /** @type {!WebInspector.NetworkLogViewColumns.De scriptor} */ (Object.assign(/** @type {!Object} */ ({}), defaultColumnConfig, cu rrentConfigColumn));
421 columnConfig.id = columnConfig.id;
422 if (columnConfig.subtitle)
423 columnConfig.titleDOMFragment = this._makeHeaderFragment(columnC onfig.title, columnConfig.subtitle);
424 this._columns.push(columnConfig);
425 }
426 this._loadColumns();
427
428 this._popoverHelper = new WebInspector.PopoverHelper(this._networkLogVie w.element);
429 this._popoverHelper.initializeCallbacks(this._getPopoverAnchor.bind(this ), this._showPopover.bind(this), this._onHidePopover.bind(this));
430
431 this._dataGrid = new WebInspector.SortableDataGrid(this._columns.map(Web Inspector.NetworkLogViewColumns._convertToDataGridDescriptor));
432 this._dataGrid.element.addEventListener("mousedown", event => {
433 if ((!this._dataGrid.selectedNode && event.button) || event.target.e nclosingNodeOrSelfWithNodeName("a"))
434 event.consume();
435 }, true);
436
437 this._dataGridScroller = this._dataGrid.scrollContainer;
438
439 this._updateColumns();
440 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChan ged, this._sortHandler, this);
441 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.ColumnsResi zed, this.updateDividersIfNeeded, this);
442 this._dataGrid.setHeaderContextMenuCallback(this._innerHeaderContextMenu .bind(this));
443
444 this._timelineGrid = new WebInspector.TimelineGrid();
445 this._timelineGrid.element.classList.add("network-timeline-grid");
446 if (!Runtime.experiments.isEnabled("canvasNetworkTimeline"))
447 this._dataGrid.element.appendChild(this._timelineGrid.element);
448
449 this._setupDropdownColumns();
450
451 this._activeTimelineSortId = WebInspector.NetworkLogViewColumns.Timeline SortIds.StartTime;
452 this._dataGrid.markColumnAsSortedBy(WebInspector.NetworkLogViewColumns._ initialSortColumn, WebInspector.DataGrid.Order.Ascending);
453
454 if (Runtime.experiments.isEnabled("canvasNetworkTimeline")) {
455 this._splitWidget = new WebInspector.SplitWidget(true, true, "networ kPanelSplitViewTimeline", 200);
456 this._splitWidget.setMainWidget(this._dataGrid.asWidget());
457 }
458 },
459
460 _setupTimeline: function()
461 {
462 this._timelineColumn = new WebInspector.NetworkTimelineColumn(this._netw orkLogView.rowHeight(), this._networkLogView.calculator());
463
464 this._timelineColumn.element.addEventListener("contextmenu", handleConte xtMenu.bind(this));
465 this._timelineColumn.element.addEventListener("mousewheel", this._onMous eWheel.bind(this, false), { passive: true });
466 this._dataGridScroller.addEventListener("mousewheel",this._onMouseWheel. bind(this, true), true);
467
468 this._timelineColumn.element.addEventListener("mousemove", event => this ._networkLogView.setHoveredRequest(this._timelineColumn.getRequestFromPoint(even t.offsetX, event.offsetY + event.target.offsetTop), event.shiftKey), true);
469 this._timelineColumn.element.addEventListener("mouseleave", this._networ kLogView.setHoveredRequest.bind(this._networkLogView, null, false), true);
470
471 this._timelineScroller = this._timelineColumn.contentElement.createChild ("div", "network-timeline-v-scroll");
472 this._timelineScroller.addEventListener("scroll", this._syncScrollers.bi nd(this), { passive: true });
473 this._timelineScrollerContent = this._timelineScroller.createChild("div" , "network-timeline-v-scroll-content");
474
475 this._dataGrid.addEventListener(WebInspector.DataGrid.Events.PaddingChan ged, () => {
476 this._timelineScrollerWidthIsStale = true;
477 this._syncScrollers();
478 });
479 this._dataGrid.addEventListener(WebInspector.ViewportDataGrid.Events.Vie wportCalculated, this._redrawTimelineColumn.bind(this));
480
481
482 this._createTimelineHeader();
483 this._timelineColumn.contentElement.classList.add("network-timeline-view ");
484
485 this._splitWidget.setSidebarWidget(this._timelineColumn);
486
487 this.switchViewMode(false);
488
489 /**
490 * @param {!Event} event
491 * @this {WebInspector.NetworkLogViewColumns}
492 */
493 function handleContextMenu(event)
494 {
495 var request = this._timelineColumn.getRequestFromPoint(event.offsetX , event.offsetY);
496 if (!request)
497 return;
498 var contextMenu = new WebInspector.ContextMenu(event);
499 this._networkLogView.handleContextMenuForRequest(contextMenu, reques t);
500 contextMenu.show();
501 }
502 },
503
504 /**
505 * @param {boolean} shouldConsume
506 * @param {!Event} event
507 */
508 _onMouseWheel: function(shouldConsume, event)
509 {
510 if (shouldConsume)
511 event.consume(true);
512 this._activeScroller.scrollTop -= event.wheelDeltaY;
513 this._syncScrollers();
514 this._networkLogView.setHoveredRequest(this._timelineColumn.getRequestFr omPoint(event.offsetX, event.offsetY), event.shiftKey);
515 },
516
517 _syncScrollers: function()
518 {
519 if (!this._timelineColumn.isShowing())
520 return;
521 this._timelineScrollerContent.style.height = this._dataGridScroller.scro llHeight + "px";
522 this._updateScrollerWidthIfNeeded();
523 this._dataGridScroller.scrollTop = this._timelineScroller.scrollTop;
524 },
525
526 _updateScrollerWidthIfNeeded: function()
527 {
528 if (this._timelineScrollerWidthIsStale) {
529 this._timelineScrollerWidthIsStale = false;
530 this._timelineColumn.setRightPadding(this._timelineScroller.offsetWi dth - this._timelineScrollerContent.offsetWidth);
531 }
532 },
533
534 _redrawTimelineColumn: function()
535 {
536 if (!this._timelineRequestsAreStale) {
537 this._updateScrollerWidthIfNeeded();
538 this._timelineColumn.update(this._activeScroller.scrollTop, this._ev entDividersShown ? this._shownEventDividers : undefined);
539 return;
540 }
541 var currentNode = this._dataGrid.rootNode();
542 var requestData = {
543 requests: [],
544 navigationRequest: null
545 };
546 while (currentNode = currentNode.traverseNextNode(true)) {
547 if (currentNode.isNavigationRequest())
548 requestData.navigationRequest = currentNode.request();
549 requestData.requests.push(currentNode.request());
550 }
551 this._timelineColumn.update(this._activeScroller.scrollTop, this._shownE ventDividers, requestData);
552 },
553
554 /**
555 * @param {?WebInspector.NetworkRequest} request
556 * @param {boolean} highlightInitiatorChain
557 */
558 setHoveredRequest: function(request, highlightInitiatorChain)
559 {
560 if (Runtime.experiments.isEnabled("canvasNetworkTimeline"))
561 this._timelineColumn.setHoveredRequest(request, highlightInitiatorCh ain);
562 },
563
564 _createTimelineHeader: function()
565 {
566 this._timelineHeaderElement = this._timelineColumn.contentElement.create Child("div", "network-timeline-header");
567 this._timelineHeaderElement.addEventListener("click", timelineHeaderClic ked.bind(this));
568 this._timelineHeaderElement.addEventListener("contextmenu", event => thi s._innerHeaderContextMenu(new WebInspector.ContextMenu(event)));
569 var innerElement = this._timelineHeaderElement.createChild("div");
570 innerElement.textContent = WebInspector.UIString("Timeline");
571 this._timelineColumnSortIcon = this._timelineHeaderElement.createChild(" div", "sort-order-icon-container").createChild("div", "sort-order-icon");
572
573 /**
574 * @this {WebInspector.NetworkLogViewColumns}
575 */
576 function timelineHeaderClicked()
577 {
578 var sortOrders = WebInspector.DataGrid.Order;
579 var sortOrder = this._dataGrid.sortOrder() === sortOrders.Ascending ? sortOrders.Descending : sortOrders.Ascending;
580 this._dataGrid.markColumnAsSortedBy("timeline", sortOrder);
581 this._sortHandler();
582 }
583 },
584
585 /**
586 * @param {!WebInspector.NetworkTimeCalculator} x
587 */
588 setCalculator: function(x)
589 {
590 if (Runtime.experiments.isEnabled("canvasNetworkTimeline"))
591 this._timelineColumn.setCalculator(x);
592 },
593
594 dataChanged: function()
595 {
596 if (Runtime.experiments.isEnabled("canvasNetworkTimeline"))
597 this._timelineRequestsAreStale = true;
598 },
599
600 _updateRowsSize: function()
601 {
602 var largeRows = !!this._networkLogLargeRowsSetting.get();
603 this._dataGrid.element.classList.toggle("small", !largeRows);
604 this._dataGrid.scheduleUpdate();
605
606 if (!Runtime.experiments.isEnabled("canvasNetworkTimeline"))
607 return;
608 this._timelineScrollerWidthIsStale = true;
609 this._timelineColumn.setRowHeight(this._networkLogView.rowHeight());
610 this._timelineScroller.classList.toggle("small", !largeRows);
611 this._timelineHeaderElement.classList.toggle("small", !largeRows);
612 this._timelineGrid.element.classList.toggle("small", !this._networkLogLa rgeRowsSetting.get());
613 this._timelineColumn.setHeaderHeight(this._timelineScroller.offsetTop);
614 },
615
616 /**
617 * @param {!Element} element
618 */
619 show: function(element)
620 {
621 if (Runtime.experiments.isEnabled("canvasNetworkTimeline"))
622 this._splitWidget.show(element);
623 else
624 this._dataGrid.asWidget().show(element);
625 },
626
627 /**
628 * @return {!WebInspector.SortableDataGrid} dataGrid
629 */
630 dataGrid: function()
631 {
632 return this._dataGrid;
633 },
634
635 _setupDropdownColumns: function()
636 {
637 for (var columnConfig of this._columns) {
638 if (!columnConfig.sortConfig || !columnConfig.sortConfig.entries)
639 continue;
640 var select = createElement("select");
641 var placeHolderOption = select.createChild("option");
642 placeHolderOption.classList.add("hidden");
643 for (var entry of columnConfig.sortConfig.entries) {
644 var option = select.createChild("option");
645 option.value = entry.id;
646 option.label = entry.title;
647 select.appendChild(option);
648 }
649 var header = this._dataGrid.headerTableHeader(columnConfig.id);
650 header.replaceChild(select, header.firstChild);
651 header.createChild("div", "sort-order-icon-container").createChild(" div", "sort-order-icon");
652 columnConfig.selectBox = select;
653 select.addEventListener("change", this._sortByDropdownItem.bind(this , columnConfig), false);
654 this._dropDownColumnSelectors.push(select);
655 }
656 },
657
658 sortByCurrentColumn: function()
659 {
660 this._sortHandler();
661 },
662
663 _sortHandler: function()
664 {
665 var columnId = this._dataGrid.sortColumnId();
666 this._networkLogView.removeAllNodeHighlights();
667 if (Runtime.experiments.isEnabled("canvasNetworkTimeline") && columnId = == "timeline") {
668 this._timelineColumnSortIcon.classList.remove("sort-ascending", "sor t-descending");
669
670 if (this._dataGrid.sortOrder() === WebInspector.DataGrid.Order.Ascen ding)
671 this._timelineColumnSortIcon.classList.add("sort-ascending");
672 else
673 this._timelineColumnSortIcon.classList.add("sort-descending");
674
675 this._timelineRequestsAreStale = true;
676 var sortFunction = WebInspector.NetworkDataGridNode.RequestPropertyC omparator.bind(null, this._activeTimelineSortId);
677 this._dataGrid.sortNodes(sortFunction, !this._dataGrid.isSortOrderAs cending());
678 return;
679 }
680
681 var columnConfig = this._columns.find(columnConfig => columnConfig.id == = columnId);
682 if (!columnConfig)
683 return;
684 if (columnConfig.sortConfig && columnConfig.sortConfig.entries) {
685 this._sortByDropdownItem(columnConfig);
686 return;
687 }
688 if (!columnConfig.sortConfig.sortingFunction)
689 return;
690
691 this._dataGrid.sortNodes(columnConfig.sortConfig.sortingFunction, !this. _dataGrid.isSortOrderAscending());
692 this._networkLogView.dataGridSorted();
693 },
694
695 /**
696 * @param {!WebInspector.NetworkLogViewColumns.Descriptor} columnConfig
697 */
698 _sortByDropdownItem: function(columnConfig)
699 {
700 this._networkLogView.removeAllNodeHighlights();
701 var selectedIndex = columnConfig.selectBox.selectedIndex;
702 if (!selectedIndex)
703 selectedIndex = 1; // Sort by first item by default.
704 var selectedItemConfig = columnConfig.sortConfig.entries[selectedIndex - 1]; // -1 because of placeholder.
705 var selectedOption = columnConfig.selectBox[selectedIndex];
706 var value = selectedOption.value;
707
708 this._dataGrid.sortNodes(selectedItemConfig.sortingFunction);
709 this._dataGrid.markColumnAsSortedBy(columnConfig.id, /** @type {!WebInsp ector.DataGrid.Order} */ (selectedItemConfig.sort));
710 if (selectedItemConfig.calculator)
711 this._networkLogView.setCalculator(this._calculatorsMap.get(selected ItemConfig.calculator));
712 columnConfig.selectBox.options[0].label = selectedItemConfig.title;
713 columnConfig.selectBox.selectedIndex = 0;
714 this._networkLogView.dataGridSorted();
715 },
716
717 _updateColumns: function()
718 {
719 if (!this._dataGrid)
720 return;
721 var visibleColumns = /** @type {!Object.<string, boolean>} */ ({});
722 if (this._gridMode) {
723 for (var columnConfig of this._columns)
724 visibleColumns[columnConfig.id] = columnConfig.visible;
725 } else {
726 visibleColumns.name = true;
727 }
728 this._dataGrid.setColumnsVisiblity(visibleColumns);
729 },
730
731 /**
732 * @param {boolean} gridMode
733 */
734 switchViewMode: function(gridMode)
735 {
736 if (this._gridMode === gridMode)
737 return;
738 this._gridMode = gridMode;
739
740 if (gridMode) {
741 if (this._dataGrid.selectedNode)
742 this._dataGrid.selectedNode.selected = false;
743 } else {
744 this._networkLogView.removeAllNodeHighlights();
745 this._popoverHelper.hidePopover();
746 }
747
748 this._networkLogView.element.classList.toggle("brief-mode", !gridMode);
749 this._updateColumns();
750
751
752 if (!Runtime.experiments.isEnabled("canvasNetworkTimeline"))
753 return;
754 // TODO(allada) Move this code into the code above.
755 if (gridMode) {
756 this._splitWidget.showBoth();
757 this._activeScroller = this._timelineScroller;
758 this._timelineScroller.scrollTop = this._dataGridScroller.scrollTop;
759 this._dataGridScroller.style.overflow = "hidden";
760 this._dataGrid.setScrollContainer(this._timelineScroller);
761 } else {
762 this._splitWidget.hideMain();
763 this._activeScroller = this._dataGridScroller;
764 this._dataGridScroller.style.overflow = "overlay";
765 this._dataGrid.setScrollContainer(this._dataGridScroller);
766 }
767 },
768
769 /**
770 * @param {!WebInspector.NetworkLogViewColumns.Descriptor} columnConfig
771 */
772 _toggleColumnVisibility: function(columnConfig)
773 {
774 this._loadColumns();
775 columnConfig.visible = !columnConfig.visible;
776 this._saveColumns();
777 this._updateColumns();
778 },
779
780 _saveColumns: function()
781 {
782 var saveableSettings = {};
783 for (var columnConfig of this._columns) {
784 saveableSettings[columnConfig.id] = {
785 visible: columnConfig.visible,
786 title: columnConfig.title
787 };
788 }
789 this._persistantSettings.set(saveableSettings);
790 },
791
792 _loadColumns: function()
793 {
794 var savedSettings = this._persistantSettings.get();
795 var columnIds = Object.keys(savedSettings);
796 for (var columnId of columnIds) {
797 var setting = savedSettings[columnId];
798 var columnConfig = this._columns.find(columnConfig => columnConfig.i d === columnId);
799 if (!columnConfig)
800 columnConfig = this._addCustomHeader(setting.title, columnId);
801 if (columnConfig.hideable && typeof setting.visible === "boolean")
802 columnConfig.visible = !!setting.visible;
803 if (typeof setting.title === "string")
804 columnConfig.title = setting.title;
805 }
806 },
807
808 /**
809 * @param {string} title
810 * @param {string} subtitle
811 * @return {!DocumentFragment}
812 */
813 _makeHeaderFragment: function(title, subtitle)
814 {
815 var fragment = createDocumentFragment();
816 fragment.createTextChild(title);
817 var subtitleDiv = fragment.createChild("div", "network-header-subtitle") ;
818 subtitleDiv.createTextChild(subtitle);
819 return fragment;
820 },
821
822 /**
823 * @param {!WebInspector.ContextMenu} contextMenu
824 */
825 _innerHeaderContextMenu: function(contextMenu)
826 {
827 if (Runtime.experiments.isEnabled("canvasNetworkTimeline")) {
828 var timelineSortIds = WebInspector.NetworkLogViewColumns.TimelineSor tIds;
829 var timelineSubMenu = contextMenu.appendSubMenuItem(WebInspector.UIS tring("Timeline"));
830 timelineSubMenu.appendCheckboxItem(WebInspector.UIString("Start Time "), setTimelineMode.bind(this, timelineSortIds.StartTime), this._activeTimelineS ortId === timelineSortIds.StartTime);
831 timelineSubMenu.appendCheckboxItem(WebInspector.UIString("Response T ime"), setTimelineMode.bind(this, timelineSortIds.ResponseTime), this._activeTim elineSortId === timelineSortIds.ResponseTime);
832 timelineSubMenu.appendCheckboxItem(WebInspector.UIString("End Time") , setTimelineMode.bind(this, timelineSortIds.EndTime), this._activeTimelineSortI d === timelineSortIds.EndTime);
833 timelineSubMenu.appendCheckboxItem(WebInspector.UIString("Total Dura tion"), setTimelineMode.bind(this, timelineSortIds.Duration), this._activeTimeli neSortId === timelineSortIds.Duration);
834 timelineSubMenu.appendCheckboxItem(WebInspector.UIString("Latency"), setTimelineMode.bind(this, timelineSortIds.Latency), this._activeTimelineSortId === timelineSortIds.Latency);
835 contextMenu.appendSeparator();
836 }
837 var columnConfigs = this._columns.filter(columnConfig => columnConfig.hi deable);
838 var nonResponseHeaders = columnConfigs.filter(columnConfig => !columnCon fig.isResponseHeader);
839 for (var columnConfig of nonResponseHeaders)
840 contextMenu.appendCheckboxItem(columnConfig.title, this._toggleColum nVisibility.bind(this, columnConfig), columnConfig.visible);
841
842 contextMenu.appendSeparator();
843
844 var responseSubMenu = contextMenu.appendSubMenuItem(WebInspector.UIStrin g("Response Headers"));
845 var responseHeaders = columnConfigs.filter(columnConfig => columnConfig. isResponseHeader);
846 for (var columnConfig of responseHeaders)
847 responseSubMenu.appendCheckboxItem(columnConfig.title, this._toggleC olumnVisibility.bind(this, columnConfig), columnConfig.visible);
848
849 responseSubMenu.appendSeparator();
850 responseSubMenu.appendItem(WebInspector.UIString("Manage Header Columns\ u2026"), this._manageCustomHeaderDialog.bind(this));
851
852 contextMenu.show();
853
854 /**
855 * @param {!WebInspector.NetworkLogViewColumns.TimelineSortIds} sortId
856 * @this {WebInspector.NetworkLogViewColumns}
857 */
858 function setTimelineMode(sortId)
859 {
860 var calculator = this._calculatorsMap.get(WebInspector.NetworkLogVie wColumns._calculatorTypes.Time);
861 var timelineSortIds = WebInspector.NetworkLogViewColumns.TimelineSor tIds;
862 if (sortId === timelineSortIds.Duration || sortId === timelineSortId s.Latency)
863 calculator = this._calculatorsMap.get(WebInspector.NetworkLogVie wColumns._calculatorTypes.Duration);
864 this._networkLogView.setCalculator(calculator);
865
866 this._activeTimelineSortId = sortId;
867 this._dataGrid.markColumnAsSortedBy("timeline", WebInspector.DataGri d.Order.Ascending);
868 this._sortHandler();
869 }
870 },
871
872 _manageCustomHeaderDialog: function()
873 {
874 var customHeaders = [];
875 for (var columnConfig of this._columns) {
876 if (columnConfig.isResponseHeader)
877 customHeaders.push({title: columnConfig.title, editable: columnC onfig.isCustomHeader});
878 }
879 var manageCustomHeaders = new WebInspector.NetworkManageCustomHeadersVie w(customHeaders, headerTitle => !!this._addCustomHeader(headerTitle), this._chan geCustomHeader.bind(this), this._removeCustomHeader.bind(this));
880 var dialog = new WebInspector.Dialog();
881 manageCustomHeaders.show(dialog.element);
882 dialog.setWrapsContent(true);
883 dialog.show();
884 },
885
886 /**
887 * @param {string} headerId
888 * @return {boolean}
889 */
890 _removeCustomHeader: function(headerId)
891 {
892 headerId = headerId.toLowerCase();
893 var index = this._columns.findIndex(columnConfig => columnConfig.id === headerId);
894 if (index === -1)
895 return false;
896 var columnConfig = this._columns.splice(index, 1);
897 this._dataGrid.removeColumn(headerId);
898 this._saveColumns();
899 this._updateColumns();
900 return true;
901 },
902
903 /**
904 * @param {string} headerTitle
905 * @param {string=} headerId
906 * @param {number=} index
907 * @return {?WebInspector.NetworkLogViewColumns.Descriptor}
908 */
909 _addCustomHeader: function(headerTitle, headerId, index)
910 {
911 if (!headerId)
912 headerId = headerTitle.toLowerCase();
913 if (index === undefined)
914 index = this._columns.length - 1;
915
916 var currentColumnConfig = this._columns.find(columnConfig => columnConfi g.id === headerId);
917 if (currentColumnConfig)
918 return null;
919
920 var columnConfig = /** @type {!WebInspector.NetworkLogViewColumns.Descr iptor} */ (Object.assign(/** @type {!Object} */ ({}), WebInspector.NetworkLogVie wColumns._defaultColumnConfig, {
921 id: headerId,
922 title: headerTitle,
923 isResponseHeader: true,
924 isCustomHeader: true,
925 visible: true,
926 sortConfig: {
927 sortingFunction: WebInspector.NetworkDataGridNode.ResponseHeader StringComparator.bind(null, headerId)
928 }
929 }));
930 this._columns.splice(index, 0, columnConfig);
931 if (this._dataGrid)
932 this._dataGrid.addColumn(WebInspector.NetworkLogViewColumns._convert ToDataGridDescriptor(columnConfig), index);
933 this._saveColumns();
934 this._updateColumns();
935 return columnConfig;
936 },
937
938 /**
939 * @param {string} oldHeaderId
940 * @param {string} newHeaderTitle
941 * @param {string=} newHeaderId
942 * @return {boolean}
943 */
944 _changeCustomHeader: function(oldHeaderId, newHeaderTitle, newHeaderId)
945 {
946 if (!newHeaderId)
947 newHeaderId = newHeaderTitle.toLowerCase();
948 oldHeaderId = oldHeaderId.toLowerCase();
949
950 var oldIndex = this._columns.findIndex(columnConfig => columnConfig.id = == oldHeaderId);
951 var oldColumnConfig = this._columns[oldIndex];
952 var currentColumnConfig = this._columns.find(columnConfig => columnConfi g.id === newHeaderId);
953 if (!oldColumnConfig || (currentColumnConfig && oldHeaderId !== newHeade rId))
954 return false;
955
956 this._removeCustomHeader(oldHeaderId);
957 this._addCustomHeader(newHeaderTitle, newHeaderId, oldIndex);
958 return true;
959 },
960
961 updateDividersIfNeeded: function()
962 {
963 // TODO(allada) Remove this code out when timeline canvas experiment is over.
964 if (Runtime.experiments.isEnabled("canvasNetworkTimeline"))
965 return;
966 if (!this._networkLogView.isShowing()) {
967 this._networkLogView.scheduleRefresh();
968 return;
969 }
970
971 var timelineOffset = this._dataGrid.columnOffset("timeline");
972 // Position timline grid location.
973 if (timelineOffset)
974 this._timelineGrid.element.style.left = timelineOffset + "px";
975
976 var calculator = this._calculatorsMap.get(WebInspector.NetworkLogViewCol umns._calculatorTypes.Time);
977 calculator.setDisplayWindow(this._timelineGrid.dividersElement.clientWid th);
978 this._timelineGrid.updateDividers(calculator, 75);
979
980 if (calculator.startAtZero) {
981 // If our current sorting method starts at zero, that means it shows all
982 // requests starting at the same point, and so onLoad event and DOMC ontent
983 // event lines really wouldn't make much sense here, so don't render them.
984 return;
985 }
986
987 this._updateEventDividers();
988 },
989
990 /**
991 * @param {!Element} element
992 * @param {!Event} event
993 * @return {!Element|!AnchorBox|undefined}
994 */
995 _getPopoverAnchor: function(element, event)
996 {
997 if (!this._gridMode)
998 return;
999 var anchor = element.enclosingNodeOrSelfWithClass("network-graph-bar") | | element.enclosingNodeOrSelfWithClass("network-graph-label");
1000 if (anchor && anchor.parentElement.request && anchor.parentElement.reque st.timing)
1001 return anchor;
1002 anchor = element.enclosingNodeOrSelfWithClass("network-script-initiated" );
1003 if (anchor && anchor.request) {
1004 var initiator = /** @type {!WebInspector.NetworkRequest} */ (anchor. request).initiator();
1005 if (initiator && initiator.stack)
1006 return anchor;
1007 }
1008 },
1009
1010 /**
1011 * @param {!Element} anchor
1012 * @param {!WebInspector.Popover} popover
1013 */
1014 _showPopover: function(anchor, popover)
1015 {
1016 var content;
1017 if (anchor.classList.contains("network-script-initiated")) {
1018 var request = /** @type {!WebInspector.NetworkRequest} */ (anchor.re quest);
1019 var initiator = /** @type {!NetworkAgent.Initiator} */ (request.init iator());
1020 content = WebInspector.DOMPresentationUtils.buildStackTracePreviewCo ntents(request.target(), this._popupLinkifier, initiator.stack);
1021 popover.setCanShrink(true);
1022 } else {
1023 content = WebInspector.RequestTimingView.createTimingTable(anchor.pa rentElement.request, this._networkLogView.timeCalculator().minimumBoundary());
1024 popover.setCanShrink(false);
1025 }
1026 popover.showForAnchor(content, anchor);
1027 },
1028
1029 _onHidePopover: function()
1030 {
1031 this._popupLinkifier.reset();
1032 },
1033
1034 /**
1035 * @param {!Array<number>} times
1036 * @param {string} className
1037 */
1038 addEventDividers: function(times, className)
1039 {
1040 if (Runtime.experiments.isEnabled("canvasNetworkTimeline")) {
1041 // TODO(allada) When we remove old timeline remove this and pass in the color.
1042 var color = "transparent";
1043 switch (className) {
1044 case "network-blue-divider":
1045 color = "hsla(240, 100%, 80%, 0.7)";
1046 break;
1047 case "network-red-divider":
1048 color = "rgba(255, 0, 0, 0.5)";
1049 break;
1050 default:
1051 return;
1052 }
1053 var currentTimes = this._shownEventDividers.get(color) || [];
1054 this._shownEventDividers.set(color, currentTimes.concat(times));
1055
1056 this._networkLogView.scheduleRefresh();
1057 return;
1058 }
1059
1060 for (var i = 0; i < times.length; ++i) {
1061 var element = createElementWithClass("div", "network-event-divider " + className);
1062 this._timelineGrid.addEventDivider(element);
1063 this._eventDividers.push({time: times[i], element: element});
1064 }
1065 // Update event dividers immediately
1066 this._updateEventDividers();
1067 // Schedule refresh in case dividers change the calculator span.
1068 this._networkLogView.scheduleRefresh();
1069 },
1070
1071 _updateEventDividers: function()
1072 {
1073 if (Runtime.experiments.isEnabled("canvasNetworkTimeline"))
1074 return;
1075 var calculator = this._calculatorsMap.get(WebInspector.NetworkLogViewCol umns._calculatorTypes.Time);
1076 for (var divider of this._eventDividers) {
1077 var timePercent = calculator.computePercentageFromEventTime(divider. time);
1078 divider.element.classList.toggle("invisible", timePercent < 0);
1079 divider.element.style.left = timePercent + "%";
1080 }
1081 },
1082
1083 hideEventDividers: function()
1084 {
1085 this._eventDividersShown = true;
1086 if (Runtime.experiments.isEnabled("canvasNetworkTimeline")) {
1087 this._redrawTimelineColumn();
1088 return;
1089 }
1090 this._timelineGrid.hideEventDividers();
1091 },
1092
1093 showEventDividers: function()
1094 {
1095 this._eventDividersShown = false;
1096 if (Runtime.experiments.isEnabled("canvasNetworkTimeline")) {
1097 this._redrawTimelineColumn();
1098 return;
1099 }
1100 this._timelineGrid.showEventDividers();
1101 },
1102
1103 /**
1104 * @param {number} time
1105 */
1106 selectFilmStripFrame: function(time)
1107 {
1108 if (Runtime.experiments.isEnabled("canvasNetworkTimeline")) {
1109 this._shownEventDividers.set(WebInspector.NetworkLogViewColumns._fil mStripDividerColor, [time]);
1110 this._redrawTimelineColumn();
1111 return;
1112 }
1113 for (var divider of this._eventDividers)
1114 divider.element.classList.toggle("network-frame-divider-selected", d ivider.time === time);
1115 },
1116
1117 clearFilmStripFrame: function()
1118 {
1119 if (Runtime.experiments.isEnabled("canvasNetworkTimeline")) {
1120 this._shownEventDividers.delete(WebInspector.NetworkLogViewColumns._ filmStripDividerColor);
1121 this._redrawTimelineColumn();
1122 return;
1123 }
1124 for (var divider of this._eventDividers)
1125 divider.element.classList.toggle("network-frame-divider-selected", f alse);
1126 }
1127 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698