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

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/timeline/TimelineTreeView.js

Issue 2473283003: DevTools: add per-frame grouping into aggregated timeline details (Closed)
Patch Set: 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 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 /** 4 /**
5 * @unrestricted 5 * @unrestricted
6 */ 6 */
7 WebInspector.TimelineTreeView = class extends WebInspector.VBox { 7 WebInspector.TimelineTreeView = class extends WebInspector.VBox {
8 constructor() { 8 constructor() {
9 super(); 9 super();
10 this.element.classList.add('timeline-tree-view'); 10 this.element.classList.add('timeline-tree-view');
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 } 149 }
150 150
151 /** 151 /**
152 * @return {!WebInspector.TimelineProfileTree.Node} 152 * @return {!WebInspector.TimelineProfileTree.Node}
153 */ 153 */
154 _buildTree() { 154 _buildTree() {
155 throw new Error('Not Implemented'); 155 throw new Error('Not Implemented');
156 } 156 }
157 157
158 /** 158 /**
159 * @param {function(!WebInspector.TracingModel.Event):(string|symbol)=} eventI dCallback 159 * @param {function(!WebInspector.TracingModel.Event, string):(string|symbol)= } eventIdCallback
160 * @return {!WebInspector.TimelineProfileTree.Node} 160 * @return {!WebInspector.TimelineProfileTree.Node}
161 */ 161 */
162 _buildTopDownTree(eventIdCallback) { 162 _buildTopDownTree(eventIdCallback) {
163 return WebInspector.TimelineProfileTree.buildTopDown( 163 return WebInspector.TimelineProfileTree.buildTopDown(
164 this._model.mainThreadEvents(), this._filters, this._startTime, this._en dTime, eventIdCallback); 164 this._model.mainThreadEvents(), this._filters, this._startTime, this._en dTime, eventIdCallback);
165 } 165 }
166 166
167 /** 167 /**
168 * @param {!Array<!WebInspector.DataGrid.ColumnDescriptor>} columns 168 * @param {!Array<!WebInspector.DataGrid.ColumnDescriptor>} columns
169 */ 169 */
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after
434 * @unrestricted 434 * @unrestricted
435 */ 435 */
436 WebInspector.AggregatedTimelineTreeView = class extends WebInspector.TimelineTre eView { 436 WebInspector.AggregatedTimelineTreeView = class extends WebInspector.TimelineTre eView {
437 /** 437 /**
438 * @param {!WebInspector.TimelineModel} model 438 * @param {!WebInspector.TimelineModel} model
439 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters 439 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
440 */ 440 */
441 constructor(model, filters) { 441 constructor(model, filters) {
442 super(); 442 super();
443 this._groupBySetting = 443 this._groupBySetting =
444 WebInspector.settings.createSetting('timelineTreeGroupBy', WebInspector. TimelineAggregator.GroupBy.Category); 444 WebInspector.settings.createSetting('timelineTreeGroupBy', WebInspector. AggregatedTimelineTreeView.GroupBy.Category);
445 this._init(model, filters); 445 this._init(model, filters);
446 var nonessentialEvents = [ 446 var nonessentialEvents = [
447 WebInspector.TimelineModel.RecordType.EventDispatch, WebInspector.Timeline Model.RecordType.FunctionCall, 447 WebInspector.TimelineModel.RecordType.EventDispatch, WebInspector.Timeline Model.RecordType.FunctionCall,
448 WebInspector.TimelineModel.RecordType.TimerFire 448 WebInspector.TimelineModel.RecordType.TimerFire
449 ]; 449 ];
450 this._filters.push(new WebInspector.ExclusiveNameFilter(nonessentialEvents)) ; 450 this._filters.push(new WebInspector.ExclusiveNameFilter(nonessentialEvents)) ;
451 this._stackView = new WebInspector.TimelineStackView(this); 451 this._stackView = new WebInspector.TimelineStackView(this);
452 this._stackView.addEventListener( 452 this._stackView.addEventListener(
453 WebInspector.TimelineStackView.Events.SelectionChanged, this._onStackVie wSelectionChanged, this); 453 WebInspector.TimelineStackView.Events.SelectionChanged, this._onStackVie wSelectionChanged, this);
454 } 454 }
(...skipping 20 matching lines...) Expand all
475 475
476 /** 476 /**
477 * @param {!WebInspector.TimelineProfileTree.Node} node 477 * @param {!WebInspector.TimelineProfileTree.Node} node
478 * @return {!{name: string, color: string}} 478 * @return {!{name: string, color: string}}
479 */ 479 */
480 _displayInfoForGroupNode(node) { 480 _displayInfoForGroupNode(node) {
481 var categories = WebInspector.TimelineUIUtils.categories(); 481 var categories = WebInspector.TimelineUIUtils.categories();
482 var color = node.id ? WebInspector.TimelineUIUtils.eventColor(node.event) : categories['other'].color; 482 var color = node.id ? WebInspector.TimelineUIUtils.eventColor(node.event) : categories['other'].color;
483 483
484 switch (this._groupBySetting.get()) { 484 switch (this._groupBySetting.get()) {
485 case WebInspector.TimelineAggregator.GroupBy.Category: 485 case WebInspector.AggregatedTimelineTreeView.GroupBy.Category:
486 var category = categories[node.id] || categories['other']; 486 var category = categories[node.id] || categories['other'];
487 return {name: category.title, color: category.color}; 487 return {name: category.title, color: category.color};
488 488
489 case WebInspector.TimelineAggregator.GroupBy.Domain: 489 case WebInspector.AggregatedTimelineTreeView.GroupBy.Domain:
490 case WebInspector.TimelineAggregator.GroupBy.Subdomain: 490 case WebInspector.AggregatedTimelineTreeView.GroupBy.Subdomain:
491 var name = node.id; 491 var name = node.id;
492 if (WebInspector.TimelineAggregator.isExtensionInternalURL(name)) 492 if (WebInspector.AggregatedTimelineTreeView._isExtensionInternalURL(name ))
493 name = WebInspector.UIString('[Chrome extensions overhead]'); 493 name = WebInspector.UIString('[Chrome extensions overhead]');
494 else if (name.startsWith('chrome-extension')) 494 else if (name.startsWith('chrome-extension'))
495 name = this._executionContextNamesByOrigin.get(name) || name; 495 name = this._executionContextNamesByOrigin.get(name) || name;
496 return {name: name || WebInspector.UIString('unattributed'), color: colo r}; 496 return {name: name || WebInspector.UIString('unattributed'), color: colo r};
497 497
498 case WebInspector.TimelineAggregator.GroupBy.EventName: 498 case WebInspector.AggregatedTimelineTreeView.GroupBy.EventName:
499 var name = node.event.name === WebInspector.TimelineModel.RecordType.JSF rame ? 499 var name = node.event.name === WebInspector.TimelineModel.RecordType.JSF rame ?
500 WebInspector.UIString('JavaScript') : 500 WebInspector.UIString('JavaScript') :
501 WebInspector.TimelineUIUtils.eventTitle(node.event); 501 WebInspector.TimelineUIUtils.eventTitle(node.event);
502 return { 502 return {
503 name: name, 503 name: name,
504 color: node.event.name === WebInspector.TimelineModel.RecordType.JSFra me ? 504 color: node.event.name === WebInspector.TimelineModel.RecordType.JSFra me ?
505 WebInspector.TimelineUIUtils.eventStyle(node.event).category.color : 505 WebInspector.TimelineUIUtils.eventStyle(node.event).category.color :
506 color 506 color
507 }; 507 };
508 508
509 case WebInspector.TimelineAggregator.GroupBy.URL: 509 case WebInspector.AggregatedTimelineTreeView.GroupBy.URL:
510 break;
511 case WebInspector.AggregatedTimelineTreeView.GroupBy.Frame:
512 var frame = this._model.pageFrameById(node.id);
513 var frameName;
514 if (frame && frame.url)
515 frameName = frame.url.startsWith('about:') && frame.name ? `"${frame.n ame}"` : frame.url;
516 else
517 frameName = WebInspector.UIString('Page');
518 return {
519 name: frameName,
520 color: color
521 };
510 break; 522 break;
511 523
512 default: 524 default:
513 console.assert(false, 'Unexpected aggregation type'); 525 console.assert(false, 'Unexpected aggregation type');
514 } 526 }
515 return {name: node.id || WebInspector.UIString('unattributed'), color: color }; 527 return {name: node.id || WebInspector.UIString('unattributed'), color: color };
516 } 528 }
517 529
518 /** 530 /**
519 * @override 531 * @override
520 * @param {!Element} parent 532 * @param {!Element} parent
521 */ 533 */
522 _populateToolbar(parent) { 534 _populateToolbar(parent) {
523 var panelToolbar = new WebInspector.Toolbar('', parent); 535 var panelToolbar = new WebInspector.Toolbar('', parent);
524 this._groupByCombobox = new WebInspector.ToolbarComboBox(this._onGroupByChan ged.bind(this)); 536 this._groupByCombobox = new WebInspector.ToolbarComboBox(this._onGroupByChan ged.bind(this));
525 /** 537 /**
526 * @param {string} name 538 * @param {string} name
527 * @param {string} id 539 * @param {string} id
528 * @this {WebInspector.TimelineTreeView} 540 * @this {WebInspector.TimelineTreeView}
529 */ 541 */
530 function addGroupingOption(name, id) { 542 function addGroupingOption(name, id) {
531 var option = this._groupByCombobox.createOption(name, '', id); 543 var option = this._groupByCombobox.createOption(name, '', id);
532 this._groupByCombobox.addOption(option); 544 this._groupByCombobox.addOption(option);
533 if (id === this._groupBySetting.get()) 545 if (id === this._groupBySetting.get())
534 this._groupByCombobox.select(option); 546 this._groupByCombobox.select(option);
535 } 547 }
536 addGroupingOption.call(this, WebInspector.UIString('No Grouping'), WebInspec tor.TimelineAggregator.GroupBy.None); 548 addGroupingOption.call(this, WebInspector.UIString('No Grouping'), WebInspec tor.AggregatedTimelineTreeView.GroupBy.None);
537 addGroupingOption.call( 549 addGroupingOption.call(
538 this, WebInspector.UIString('Group by Activity'), WebInspector.TimelineA ggregator.GroupBy.EventName); 550 this, WebInspector.UIString('Group by Activity'), WebInspector.Aggregate dTimelineTreeView.GroupBy.EventName);
539 addGroupingOption.call( 551 addGroupingOption.call(
540 this, WebInspector.UIString('Group by Category'), WebInspector.TimelineA ggregator.GroupBy.Category); 552 this, WebInspector.UIString('Group by Category'), WebInspector.Aggregate dTimelineTreeView.GroupBy.Category);
541 addGroupingOption.call( 553 addGroupingOption.call(
542 this, WebInspector.UIString('Group by Domain'), WebInspector.TimelineAgg regator.GroupBy.Domain); 554 this, WebInspector.UIString('Group by Domain'), WebInspector.AggregatedT imelineTreeView.GroupBy.Domain);
543 addGroupingOption.call( 555 addGroupingOption.call(
544 this, WebInspector.UIString('Group by Subdomain'), WebInspector.Timeline Aggregator.GroupBy.Subdomain); 556 this, WebInspector.UIString('Group by Subdomain'), WebInspector.Aggregat edTimelineTreeView.GroupBy.Subdomain);
545 addGroupingOption.call(this, WebInspector.UIString('Group by URL'), WebInspe ctor.TimelineAggregator.GroupBy.URL); 557 addGroupingOption.call(this, WebInspector.UIString('Group by URL'), WebInspe ctor.AggregatedTimelineTreeView.GroupBy.URL);
558 addGroupingOption.call(this, WebInspector.UIString('Group by Frame'), WebIns pector.AggregatedTimelineTreeView.GroupBy.Frame);
546 panelToolbar.appendToolbarItem(this._groupByCombobox); 559 panelToolbar.appendToolbarItem(this._groupByCombobox);
547 } 560 }
548 561
549 /** 562 /**
550 * @param {!WebInspector.TimelineProfileTree.Node} treeNode 563 * @param {!WebInspector.TimelineProfileTree.Node} treeNode
551 * @return {!Array<!WebInspector.TimelineProfileTree.Node>} 564 * @return {!Array<!WebInspector.TimelineProfileTree.Node>}
552 */ 565 */
553 _buildHeaviestStack(treeNode) { 566 _buildHeaviestStack(treeNode) {
554 console.assert(!!treeNode.parent, 'Attempt to build stack for tree root'); 567 console.assert(!!treeNode.parent, 'Attempt to build stack for tree root');
555 var result = []; 568 var result = [];
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 * @return {boolean} 603 * @return {boolean}
591 */ 604 */
592 _showDetailsForNode(node) { 605 _showDetailsForNode(node) {
593 var stack = this._buildHeaviestStack(node); 606 var stack = this._buildHeaviestStack(node);
594 this._stackView.setStack(stack, node); 607 this._stackView.setStack(stack, node);
595 this._stackView.show(this._detailsView.element); 608 this._stackView.show(this._detailsView.element);
596 return true; 609 return true;
597 } 610 }
598 611
599 /** 612 /**
600 * @return {!WebInspector.TimelineAggregator} 613 * @param {!WebInspector.AggregatedTimelineTreeView.GroupBy} groupBy
614 * @return {function(!WebInspector.TracingModel.Event, string):string}
601 */ 615 */
602 _createAggregator() { 616 _groupingFunction(groupBy) {
603 return new WebInspector.TimelineAggregator( 617 /**
604 event => WebInspector.TimelineUIUtils.eventStyle(event).title, 618 * @param {!WebInspector.TracingModel.Event} event
605 event => WebInspector.TimelineUIUtils.eventStyle(event).category.name); 619 * @return {string}
620 */
621 function groupByURL(event) {
dgozman 2016/11/07 17:43:16 This function does not take second string paramete
alph 2016/11/07 19:10:02 It is opposite. The function does not need the sec
622 return WebInspector.TimelineProfileTree.eventURL(event) || '';
623 }
624
625 /**
626 * @param {boolean} groupSubdomains
627 * @param {!WebInspector.TracingModel.Event} event
628 * @return {string}
629 */
630 function groupByDomain(groupSubdomains, event) {
631 var url = WebInspector.TimelineProfileTree.eventURL(event) || '';
632 if (WebInspector.AggregatedTimelineTreeView._isExtensionInternalURL(url))
633 return WebInspector.AggregatedTimelineTreeView._extensionInternalPrefix;
634 var parsedURL = url.asParsedURL();
635 if (!parsedURL)
636 return '';
637 if (parsedURL.scheme === 'chrome-extension')
638 return parsedURL.scheme + '://' + parsedURL.host;
639 if (!groupSubdomains)
640 return parsedURL.host;
641 if (/^[.0-9]+$/.test(parsedURL.host))
642 return parsedURL.host;
643 var domainMatch = /([^.]*\.)?[^.]*$/.exec(parsedURL.host);
644 return domainMatch && domainMatch[0] || '';
645 }
646
647 switch (groupBy) {
648 case WebInspector.AggregatedTimelineTreeView.GroupBy.None:
649 return () => Symbol('uniqueGroupId');
650 case WebInspector.AggregatedTimelineTreeView.GroupBy.EventName:
651 return event => WebInspector.TimelineUIUtils.eventStyle(event).title;
652 case WebInspector.AggregatedTimelineTreeView.GroupBy.Category:
653 return event => WebInspector.TimelineUIUtils.eventStyle(event).category. name;
654 case WebInspector.AggregatedTimelineTreeView.GroupBy.Subdomain:
655 return groupByDomain.bind(null, false);
656 case WebInspector.AggregatedTimelineTreeView.GroupBy.Domain:
657 return groupByDomain.bind(null, true);
658 case WebInspector.AggregatedTimelineTreeView.GroupBy.URL:
659 return groupByURL;
660 case WebInspector.AggregatedTimelineTreeView.GroupBy.Frame:
661 return (event, pageFrameId) => pageFrameId;
alph 2016/11/07 19:10:02 Adding an extra argument for a single grouping mod
662 default:
663 console.assert(false, `Unexpected aggregation setting: ${groupBy}`);
664 return () => Symbol('uniqueGroupId');
665 }
606 } 666 }
667
668 /**
669 * @param {string} url
670 * @return {boolean}
671 */
672 static _isExtensionInternalURL(url) {
673 return url.startsWith(WebInspector.AggregatedTimelineTreeView._extensionInte rnalPrefix);
674 }
675 };
676
677 WebInspector.AggregatedTimelineTreeView._extensionInternalPrefix = 'extensions:: ';
678
679 /**
680 * @enum {string}
681 */
682 WebInspector.AggregatedTimelineTreeView.GroupBy = {
683 None: 'None',
684 EventName: 'EventName',
685 Category: 'Category',
686 Domain: 'Domain',
687 Subdomain: 'Subdomain',
688 URL: 'URL',
689 Frame: 'Frame'
607 }; 690 };
608 691
609 /** 692 /**
610 * @unrestricted 693 * @unrestricted
611 */ 694 */
612 WebInspector.CallTreeTimelineTreeView = class extends WebInspector.AggregatedTim elineTreeView { 695 WebInspector.CallTreeTimelineTreeView = class extends WebInspector.AggregatedTim elineTreeView {
613 /** 696 /**
614 * @param {!WebInspector.TimelineModel} model 697 * @param {!WebInspector.TimelineModel} model
615 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters 698 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
616 */ 699 */
617 constructor(model, filters) { 700 constructor(model, filters) {
618 super(model, filters); 701 super(model, filters);
619 this._dataGrid.markColumnAsSortedBy('total', WebInspector.DataGrid.Order.Des cending); 702 this._dataGrid.markColumnAsSortedBy('total', WebInspector.DataGrid.Order.Des cending);
620 } 703 }
621 704
622 /** 705 /**
623 * @override 706 * @override
624 * @return {!WebInspector.TimelineProfileTree.Node} 707 * @return {!WebInspector.TimelineProfileTree.Node}
625 */ 708 */
626 _buildTree() { 709 _buildTree() {
627 var topDown = this._buildTopDownTree(WebInspector.TimelineAggregator.eventId ); 710 var grouping = this._groupBySetting.get();
628 return this._createAggregator().performGrouping(topDown, this._groupBySettin g.get()); 711 var topDown = this._buildTopDownTree(this._groupingFunction(grouping));
712 if (grouping === WebInspector.AggregatedTimelineTreeView.GroupBy.None)
713 return topDown;
714 return new WebInspector.TimelineAggregator().performGrouping(topDown);
629 } 715 }
630 }; 716 };
631 717
632 /** 718 /**
633 * @unrestricted 719 * @unrestricted
634 */ 720 */
635 WebInspector.BottomUpTimelineTreeView = class extends WebInspector.AggregatedTim elineTreeView { 721 WebInspector.BottomUpTimelineTreeView = class extends WebInspector.AggregatedTim elineTreeView {
636 /** 722 /**
637 * @param {!WebInspector.TimelineModel} model 723 * @param {!WebInspector.TimelineModel} model
638 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters 724 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
639 */ 725 */
640 constructor(model, filters) { 726 constructor(model, filters) {
641 super(model, filters); 727 super(model, filters);
642 this._dataGrid.markColumnAsSortedBy('self', WebInspector.DataGrid.Order.Desc ending); 728 this._dataGrid.markColumnAsSortedBy('self', WebInspector.DataGrid.Order.Desc ending);
643 } 729 }
644 730
645 /** 731 /**
646 * @override 732 * @override
647 * @return {!WebInspector.TimelineProfileTree.Node} 733 * @return {!WebInspector.TimelineProfileTree.Node}
648 */ 734 */
649 _buildTree() { 735 _buildTree() {
650 var topDown = this._buildTopDownTree(WebInspector.TimelineAggregator.eventId ); 736 var topDown = this._buildTopDownTree(this._groupingFunction(this._groupBySet ting.get()));
651 return WebInspector.TimelineProfileTree.buildBottomUp( 737 return WebInspector.TimelineProfileTree.buildBottomUp(topDown);
652 topDown, this._createAggregator().groupFunction(this._groupBySetting.get ()));
653 } 738 }
654 }; 739 };
655 740
656 /** 741 /**
657 * @unrestricted 742 * @unrestricted
658 */ 743 */
659 WebInspector.EventsTimelineTreeView = class extends WebInspector.TimelineTreeVie w { 744 WebInspector.EventsTimelineTreeView = class extends WebInspector.TimelineTreeVie w {
660 /** 745 /**
661 * @param {!WebInspector.TimelineModel} model 746 * @param {!WebInspector.TimelineModel} model
662 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters 747 * @param {!Array<!WebInspector.TimelineModel.Filter>} filters
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
839 924
840 _onSelectionChanged() { 925 _onSelectionChanged() {
841 this.dispatchEventToListeners(WebInspector.TimelineStackView.Events.Selectio nChanged); 926 this.dispatchEventToListeners(WebInspector.TimelineStackView.Events.Selectio nChanged);
842 } 927 }
843 }; 928 };
844 929
845 /** @enum {symbol} */ 930 /** @enum {symbol} */
846 WebInspector.TimelineStackView.Events = { 931 WebInspector.TimelineStackView.Events = {
847 SelectionChanged: Symbol('SelectionChanged') 932 SelectionChanged: Symbol('SelectionChanged')
848 }; 933 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698