Changeset 243301 in webkit


Ignore:
Timestamp:
Mar 21, 2019 11:03:02 AM (5 years ago)
Author:
Devin Rousso
Message:

Web Inspector: Timelines: flatten the overview to show all records, one per line
https://bugs.webkit.org/show_bug.cgi?id=191901
<rdar://problem/46423618>

Reviewed by Timothy Hatcher.

  • UserInterface/Views/OverviewTimelineView.js:

(WI.OverviewTimelineView):
(WI.OverviewTimelineView.prototype.closed):
(WI.OverviewTimelineView.prototype.get navigationItems): Added.
(WI.OverviewTimelineView.prototype.reset):
(WI.OverviewTimelineView.prototype.layout):
(WI.OverviewTimelineView.prototype.get _relevantTimelines): Added.
(WI.OverviewTimelineView.prototype.get _shouldGroupBySourceCode): Added.
(WI.OverviewTimelineView.prototype._loadExistingRecords): Added.
(WI.OverviewTimelineView.prototype._insertDataGridNode):
(WI.OverviewTimelineView.prototype._addResourceToDataGridIfNeeded):
(WI.OverviewTimelineView.prototype._addSourceCodeTimeline):
(WI.OverviewTimelineView.prototype._processPendingRepresentedObjects):
(WI.OverviewTimelineView.prototype._handleGroupBySourceCodeSettingChanged): Added.
(WI.OverviewTimelineView.prototype._handleGroupBySourceCodeNavigationItemCheckedDidChange): Added.
(WI.OverviewTimelineView.prototype._handleTimelineRecordAdded): Added.
(WI.OverviewTimelineView.prototype._sourceCodeTimelineAdded):
(WI.OverviewTimelineView.prototype._networkTimelineRecordAdded): Deleted.
Listen for new records on all timelines. Add each record as a new line. Since each timeline
has different data to display, only show the "name" and "graph" for all records.

  • UserInterface/Views/TimelineRecordingContentView.js:

(WI.TimelineRecordingContentView):
(WI.TimelineRecordingContentView.prototype._currentContentViewDidChange):
(WI.TimelineRecordingContentView.prototype._updateImportedView): Deleted.
When viewing the overview of an imported recording, show the non-grouped overview.

  • UserInterface/Models/TimelineRecording.js:

(WI.TimelineRecording.prototype.addRecord):
(WI.TimelineRecording.prototype._keyForRecord):
Drive-by: show Media timeline events under the owner frame's resource when grouped.

  • UserInterface/Views/TimelineRecordBar.css:

(.timeline-record-bar.timeline-record-type-script.garbage-collected > .segment, .timeline-record-bar.timeline-record-type-heap-allocations > .segment): Added.
(.timeline-record-bar.timeline-record-type-script.garbage-collected > .segment): Deleted.

  • UserInterface/Base/Setting.js:

Add setting for controlling the Timeline overview grouping.

  • UserInterface/Main.html:
  • UserInterface/Views/SourceCodeTimelineTreeElement.js: Removed.
  • UserInterface/Views/TimelineRecordingImportedView.js: Removed.
  • UserInterface/Views/TimelineRecordingImportedView.css: Removed.

Remove unused files.

  • Localizations/en.lproj/localizedStrings.js:
Location:
trunk/Source/WebInspectorUI
Files:
3 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r243300 r243301  
     12019-03-21  Devin Rousso  <drousso@apple.com>
     2
     3        Web Inspector: Timelines: flatten the overview to show all records, one per line
     4        https://bugs.webkit.org/show_bug.cgi?id=191901
     5        <rdar://problem/46423618>
     6
     7        Reviewed by Timothy Hatcher.
     8
     9        * UserInterface/Views/OverviewTimelineView.js:
     10        (WI.OverviewTimelineView):
     11        (WI.OverviewTimelineView.prototype.closed):
     12        (WI.OverviewTimelineView.prototype.get navigationItems): Added.
     13        (WI.OverviewTimelineView.prototype.reset):
     14        (WI.OverviewTimelineView.prototype.layout):
     15        (WI.OverviewTimelineView.prototype.get _relevantTimelines): Added.
     16        (WI.OverviewTimelineView.prototype.get _shouldGroupBySourceCode): Added.
     17        (WI.OverviewTimelineView.prototype._loadExistingRecords): Added.
     18        (WI.OverviewTimelineView.prototype._insertDataGridNode):
     19        (WI.OverviewTimelineView.prototype._addResourceToDataGridIfNeeded):
     20        (WI.OverviewTimelineView.prototype._addSourceCodeTimeline):
     21        (WI.OverviewTimelineView.prototype._processPendingRepresentedObjects):
     22        (WI.OverviewTimelineView.prototype._handleGroupBySourceCodeSettingChanged): Added.
     23        (WI.OverviewTimelineView.prototype._handleGroupBySourceCodeNavigationItemCheckedDidChange): Added.
     24        (WI.OverviewTimelineView.prototype._handleTimelineRecordAdded): Added.
     25        (WI.OverviewTimelineView.prototype._sourceCodeTimelineAdded):
     26        (WI.OverviewTimelineView.prototype._networkTimelineRecordAdded): Deleted.
     27        Listen for new records on all timelines. Add each record as a new line. Since each timeline
     28        has different data to display, only show the "name" and "graph" for all records.
     29
     30        * UserInterface/Views/TimelineRecordingContentView.js:
     31        (WI.TimelineRecordingContentView):
     32        (WI.TimelineRecordingContentView.prototype._currentContentViewDidChange):
     33        (WI.TimelineRecordingContentView.prototype._updateImportedView): Deleted.
     34        When viewing the overview of an imported recording, show the non-grouped overview.
     35
     36        * UserInterface/Models/TimelineRecording.js:
     37        (WI.TimelineRecording.prototype.addRecord):
     38        (WI.TimelineRecording.prototype._keyForRecord):
     39        Drive-by: show Media timeline events under the owner frame's resource when grouped.
     40
     41        * UserInterface/Views/TimelineRecordBar.css:
     42        (.timeline-record-bar.timeline-record-type-script.garbage-collected > .segment, .timeline-record-bar.timeline-record-type-heap-allocations > .segment): Added.
     43        (.timeline-record-bar.timeline-record-type-script.garbage-collected > .segment): Deleted.
     44
     45        * UserInterface/Base/Setting.js:
     46        Add setting for controlling the Timeline overview grouping.
     47
     48        * UserInterface/Main.html:
     49        * UserInterface/Views/SourceCodeTimelineTreeElement.js: Removed.
     50        * UserInterface/Views/TimelineRecordingImportedView.js: Removed.
     51        * UserInterface/Views/TimelineRecordingImportedView.css: Removed.
     52        Remove unused files.
     53
     54        * Localizations/en.lproj/localizedStrings.js:
     55
    1562019-03-21  Devin Rousso  <drousso@apple.com>
    257
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r243269 r243301  
    515515localizedStrings["Grammar"] = "Grammar";
    516516localizedStrings["Group"] = "Group";
     517localizedStrings["Group By Resource"] = "Group By Resource";
    517518localizedStrings["Group Media Requests"] = "Group Media Requests";
    518519localizedStrings["Group by Event"] = "Group by Event";
     
    564565localizedStrings["Imported - %s"] = "Imported - %s";
    565566localizedStrings["Imported Recordings"] = "Imported Recordings";
    566 localizedStrings["Imported Timeline Recording"] = "Imported Timeline Recording";
    567567localizedStrings["Imported \u2014 %s"] = "Imported \u2014 %s";
    568568localizedStrings["Incomplete"] = "Incomplete";
  • trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js

    r243220 r243301  
    157157    tabSize: new WI.Setting("tab-size", 4),
    158158    timelinesAutoStop: new WI.Setting("timelines-auto-stop", true),
     159    timelineOverviewGroupBySourceCode: new WI.Setting("timeline-overview-group-by-source-code", true),
    159160    zoomFactor: new WI.Setting("zoom-factor", 1),
    160161
  • trunk/Source/WebInspectorUI/UserInterface/Main.html

    r243024 r243301  
    223223    <link rel="stylesheet" href="Views/TimelineRecordFrame.css">
    224224    <link rel="stylesheet" href="Views/TimelineRecordingContentView.css">
    225     <link rel="stylesheet" href="Views/TimelineRecordingImportedView.css">
    226225    <link rel="stylesheet" href="Views/TimelineRuler.css">
    227226    <link rel="stylesheet" href="Views/TimelineTabContentView.css">
     
    799798    <script src="Views/SourceCodeTextEditor.js"></script>
    800799    <script src="Views/SourceCodeTimelineTimelineDataGridNode.js"></script>
    801     <script src="Views/SourceCodeTimelineTreeElement.js"></script>
    802800    <script src="Views/SourcesNavigationSidebarPanel.js"></script>
    803801    <script src="Views/SourceMapResourceTreeElement.js"></script>
     
    828826    <script src="Views/TimelineRecordingContentView.js"></script>
    829827    <script src="Views/TimelineRecordingProgressView.js"></script>
    830     <script src="Views/TimelineRecordingImportedView.js"></script>
    831828    <script src="Views/TimelineRuler.js"></script>
    832829    <script src="Views/TitleView.js"></script>
  • trunk/Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js

    r243024 r243301  
    239239    }
    240240
    241     sourceCodeTimelinesForSourceCode(sourceCode)
    242     {
    243         var timelines = this._sourceCodeTimelinesMap.get(sourceCode);
    244         if (!timelines)
    245             return [];
    246         return [...timelines.values()];
     241    get sourceCodeTimelines()
     242    {
     243        let timelines = [];
     244        for (let timelinesForSourceCode of this._sourceCodeTimelinesMap.values())
     245            timelines = timelines.concat(Array.from(timelinesForSourceCode.values()));
     246        return timelines;
    247247    }
    248248
     
    309309            || record.type === WI.TimelineRecord.Type.CPU
    310310            || record.type === WI.TimelineRecord.Type.Memory
    311             || record.type === WI.TimelineRecord.Type.HeapAllocations
    312             || record.type === WI.TimelineRecord.Type.Media)
     311            || record.type === WI.TimelineRecord.Type.HeapAllocations)
    313312            return;
    314313
     
    317316
    318317        // Add the record to the source code timelines.
    319         var activeMainResource = WI.networkManager.mainFrame.provisionalMainResource || WI.networkManager.mainFrame.mainResource;
    320         var sourceCode = record.sourceCodeLocation ? record.sourceCodeLocation.sourceCode : activeMainResource;
     318        let sourceCode = null;
     319        if (record.sourceCodeLocation)
     320            sourceCode = record.sourceCodeLocation.sourceCode;
     321        else if (record.type === WI.TimelineRecord.Type.Media) {
     322            if (record.domNode && record.domNode.frame)
     323                sourceCode = record.domNode.frame.mainResource;
     324        }
     325        if (!sourceCode)
     326            sourceCode = WI.networkManager.mainFrame.provisionalMainResource || WI.networkManager.mainFrame.mainResource;
    321327
    322328        var sourceCodeTimelines = this._sourceCodeTimelinesMap.get(sourceCode);
     
    453459    {
    454460        var key = record.type;
    455         if (record instanceof WI.ScriptTimelineRecord || record instanceof WI.LayoutTimelineRecord || record instanceof WI.MediaTimelineRecord)
     461        if (record instanceof WI.ScriptTimelineRecord || record instanceof WI.LayoutTimelineRecord)
    456462            key += ":" + record.eventType;
    457463        if (record instanceof WI.ScriptTimelineRecord && record.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched)
    458464            key += ":" + record.details;
     465        if (record instanceof WI.MediaTimelineRecord) {
     466            key += ":" + record.eventType;
     467            if (record.eventType === WI.MediaTimelineRecord.EventType.DOMEvent) {
     468                if (record.domEvent && record.domEvent.eventName)
     469                    key += ":" + record.domEvent.eventName;
     470            } else if (record.eventType === WI.MediaTimelineRecord.EventType.LowPower)
     471                key += ":" + (record.isLowPower ? "enabled" : "disabled");
     472        }
    459473        if (record.sourceCodeLocation)
    460474            key += ":" + record.sourceCodeLocation.lineNumber + ":" + record.sourceCodeLocation.columnNumber;
  • trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js

    r243213 r243301  
    4848        this._cachedData.startTime = this.record.startTime - (this.graphDataSource ? this.graphDataSource.zeroTime : 0);
    4949        this._cachedData.totalTime = this.record.duration;
    50         this._cachedData.location = this.record.initiatorCallFrame;
     50        this._cachedData.initiator = this.record.initiatorCallFrame;
    5151        return this._cachedData;
    5252    }
     
    7474        case "totalTime":
    7575            return isNaN(value) ? emDash : Number.secondsToString(value, higherResolution);
     76
     77        case "source": // Timeline Overview
     78            return super.createCellContent("initiator", cell);
    7679        }
    7780
  • trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js

    r243213 r243301  
    3232        console.assert(timeline.type === WI.TimelineRecord.Type.Layout, timeline);
    3333
    34         let columns = {type: {}, name: {}, location: {}, area: {}, width: {}, height: {}, startTime: {}, totalTime: {}};
     34        let columns = {type: {}, name: {}, initiator: {}, area: {}, width: {}, height: {}, startTime: {}, totalTime: {}};
    3535
    3636        columns.name.title = WI.UIString("Type");
     
    5353        this._scopeBar = columns.type.scopeBar;
    5454
    55         columns.location.title = WI.UIString("Initiator");
    56         columns.location.width = "25%";
     55        columns.initiator.title = WI.UIString("Initiator");
     56        columns.initiator.width = "25%";
    5757
    5858        columns.area.title = WI.UIString("Area");
  • trunk/Source/WebInspectorUI/UserInterface/Views/MediaTimelineDataGridNode.js

    r243213 r243301  
    5959            return value;
    6060
     61        case "source": // Timeline Overview
    6162        case "element":
    6263            return value ? WI.linkifyNodeReference(value) : emDash;
  • trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js

    r243213 r243301  
    3232        console.assert(timeline.type === WI.TimelineRecord.Type.Network);
    3333
    34         let columns = {name: {}, domain: {}, type: {}, method: {}, scheme: {}, statusCode: {}, cached: {}, protocol: {}, priority: {}, remoteAddress: {}, connectionIdentifier: {}, size: {}, transferSize: {}, requestSent: {}, latency: {}, duration: {}, graph: {}};
     34        let columns = {name: {}, domain: {}, type: {}, method: {}, scheme: {}, statusCode: {}, cached: {}, protocol: {}, priority: {}, remoteAddress: {}, connectionIdentifier: {}, size: {}, transferSize: {}, requestSent: {}, latency: {}, duration: {}, initiator: {}, graph: {}};
    3535
    3636        columns.name.title = WI.UIString("Name");
  • trunk/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js

    r243213 r243301  
    2828    constructor(recording, extraArguments)
    2929    {
     30        console.assert(recording instanceof WI.TimelineRecording);
     31
    3032        super(recording, extraArguments);
    3133
    3234        this._recording = recording;
    33 
    34         let columns = {name: {}, graph: {}};
     35        this._pendingRepresentedObjects = [];
     36        this._resourceDataGridNodeMap = new Map;
     37
     38        if (WI.TimelineRecording.sourceCodeTimelinesSupported() && !this._recording.imported) {
     39            WI.settings.timelineOverviewGroupBySourceCode.addEventListener(WI.Setting.Event.Changed, this._handleGroupBySourceCodeSettingChanged, this);
     40
     41            this._groupBySourceCodeNavigationItem = new WI.CheckboxNavigationItem("overview-timeline-group-by-resource", WI.UIString("Group By Resource"), WI.settings.timelineOverviewGroupBySourceCode.value);
     42            this._groupBySourceCodeNavigationItem.addEventListener(WI.CheckboxNavigationItem.Event.CheckedDidChange, this._handleGroupBySourceCodeNavigationItemCheckedDidChange, this);
     43        }
     44
     45        let columns = {name: {}, source: {}, graph: {}};
    3546
    3647        columns.name.title = WI.UIString("Name");
    3748        columns.name.width = "20%";
    3849        columns.name.icon = true;
    39         columns.name.disclosure = true;
     50        columns.name.locked = true;
     51        if (this._shouldGroupBySourceCode)
     52            columns.name.disclosure = true;
     53
     54        columns.source.title = WI.UIString("Source");
     55        columns.source.width = "10%";
     56        columns.source.icon = true;
     57        columns.source.locked = true;
     58        if (this._shouldGroupBySourceCode)
     59            columns.source.hidden = true;
    4060
    4161        this._timelineRuler = new WI.TimelineRuler;
    4262        this._timelineRuler.allowsClippedLabels = true;
    4363
    44         columns.graph.width = "80%";
     64        columns.graph.width = "70%";
    4565        columns.graph.headerView = this._timelineRuler;
    46 
    47         this._dataGrid = new WI.DataGrid(columns);
     66        columns.graph.locked = true;
     67
     68        this._dataGrid = new WI.TimelineDataGrid(columns);
    4869
    4970        this.setupDataGrid(this._dataGrid);
     
    5374
    5475        this.element.classList.add("overview");
    55         if (!this._recording.imported)
    56             this.addSubview(this._dataGrid);
    57 
    58         this._networkTimeline = recording.timelines.get(WI.TimelineRecord.Type.Network);
    59         if (this._networkTimeline)
    60             this._networkTimeline.addEventListener(WI.Timeline.Event.RecordAdded, this._networkTimelineRecordAdded, this);
     76        this.addSubview(this._dataGrid);
     77
     78        for (let timeline of this._relevantTimelines)
     79            timeline.addEventListener(WI.Timeline.Event.RecordAdded, this._handleTimelineRecordAdded, this);
    6180
    6281        recording.addEventListener(WI.TimelineRecording.Event.SourceCodeTimelineAdded, this._sourceCodeTimelineAdded, this);
     
    6483        recording.addEventListener(WI.TimelineRecording.Event.Reset, this._recordingReset, this);
    6584
    66         this._pendingRepresentedObjects = [];
    67         this._resourceDataGridNodeMap = new Map;
     85        this._loadExistingRecords();
    6886    }
    6987
     
    89107    closed()
    90108    {
    91         if (this._networkTimeline)
    92             this._networkTimeline.removeEventListener(null, null, this);
     109        for (let timeline of this._recording.timelines.values())
     110            timeline.removeEventListener(null, null, this);
     111
    93112        this._recording.removeEventListener(null, null, this);
     113    }
     114
     115    get navigationItems()
     116    {
     117        let navigationItems = [];
     118        if (this._groupBySourceCodeNavigationItem)
     119            navigationItems.push(this._groupBySourceCodeNavigationItem);
     120        return navigationItems;
    94121    }
    95122
     
    120147        super.reset();
    121148
    122         this._dataGrid.removeChildren();
     149        this._dataGrid.reset();
    123150
    124151        this._pendingRepresentedObjects = [];
     152        this._resourceDataGridNodeMap.clear();
    125153    }
    126154
     
    142170    layout()
    143171    {
    144         if (this._recording.imported)
    145             return;
    146 
    147172        let oldZeroTime = this._timelineRuler.zeroTime;
    148173        let oldStartTime = this._timelineRuler.startTime;
     
    170195    // Private
    171196
     197    get _relevantTimelines()
     198    {
     199        let timelines = [];
     200        for (let [type, timeline] of this._recording.timelines) {
     201            if (type === WI.TimelineRecord.Type.RenderingFrame || type === WI.TimelineRecord.Type.CPU || type === WI.TimelineRecord.Type.Memory)
     202                continue;
     203
     204            timelines.push(timeline);
     205        }
     206        return timelines;
     207    }
     208
     209    get _shouldGroupBySourceCode()
     210    {
     211        // Always show imported records as non-grouped.
     212        if (this._recording.imported)
     213            return false;
     214
     215        return WI.TimelineRecording.sourceCodeTimelinesSupported() && WI.settings.timelineOverviewGroupBySourceCode.value;
     216    }
     217
     218    _loadExistingRecords()
     219    {
     220        this._pendingRepresentedObjects = [];
     221        this._resourceDataGridNodeMap.clear();
     222
     223        this._dataGrid.removeChildren();
     224
     225        if (this._shouldGroupBySourceCode) {
     226            let networkTimeline = this._recording.timelines.get(WI.TimelineRecord.Type.Network);
     227            if (networkTimeline)
     228                this._pendingRepresentedObjects = this._pendingRepresentedObjects.concat(networkTimeline.records.map((record) => record.resource));
     229
     230            this._pendingRepresentedObjects = this._pendingRepresentedObjects.concat(this._recording.sourceCodeTimelines);
     231        } else {
     232            for (let timeline of this._relevantTimelines)
     233                this._pendingRepresentedObjects = this._pendingRepresentedObjects.concat(timeline.records);
     234        }
     235
     236        this.needsLayout();
     237    }
     238
    172239    _compareDataGridNodesByStartTime(a, b)
    173240    {
     
    196263        console.assert(!dataGridNode.parent);
    197264
    198         if (parentDataGridNode)
    199             parentDataGridNode.insertChild(dataGridNode, insertionIndexForObjectInListSortedByFunction(dataGridNode, parentDataGridNode.children, this._compareDataGridNodesByStartTime.bind(this)));
    200         else
    201             this._dataGrid.appendChild(dataGridNode);
     265        if (!parentDataGridNode)
     266            parentDataGridNode = this._dataGrid;
     267
     268        parentDataGridNode.insertChild(dataGridNode, insertionIndexForObjectInListSortedByFunction(dataGridNode, parentDataGridNode.children, this._compareDataGridNodesByStartTime));
    202269    }
    203270
     
    210277        // FIXME: replace with this._dataGrid.findDataGridNode(resource) once <https://webkit.org/b/155305> is fixed.
    211278        let dataGridNode = this._resourceDataGridNodeMap.get(resource);
    212         if (dataGridNode)
    213             return dataGridNode;
    214 
    215         let parentFrame = resource.parentFrame;
    216         if (!parentFrame)
    217             return null;
    218 
    219         let resourceTimelineRecord = this._networkTimeline ? this._networkTimeline.recordForResource(resource) : null;
    220         if (!resourceTimelineRecord)
    221             resourceTimelineRecord = new WI.ResourceTimelineRecord(resource);
    222 
    223         let resourceDataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, {
    224             graphDataSource: this,
    225             includesGraph: true,
    226         });
    227         this._resourceDataGridNodeMap.set(resource, resourceDataGridNode);
    228 
    229         let expandedByDefault = false;
    230         if (parentFrame.mainResource === resource || parentFrame.provisionalMainResource === resource) {
    231             parentFrame = parentFrame.parentFrame;
    232             expandedByDefault = !parentFrame; // Main frame expands by default.
    233         }
    234 
    235         if (expandedByDefault)
    236             resourceDataGridNode.expand();
    237 
    238         let parentDataGridNode = null;
    239         if (parentFrame) {
    240             // Find the parent main resource, adding it if needed, to append this resource as a child.
    241             let parentResource = parentFrame.provisionalMainResource || parentFrame.mainResource;
    242 
    243             parentDataGridNode = this._addResourceToDataGridIfNeeded(parentResource);
    244             console.assert(parentDataGridNode);
    245             if (!parentDataGridNode)
     279        if (!dataGridNode) {
     280            let resourceTimelineRecord = this._networkTimeline ? this._networkTimeline.recordForResource(resource) : null;
     281            if (!resourceTimelineRecord)
     282                resourceTimelineRecord = new WI.ResourceTimelineRecord(resource);
     283
     284            dataGridNode = new WI.ResourceTimelineDataGridNode(resourceTimelineRecord, {
     285                graphDataSource: this,
     286                includesGraph: true,
     287            });
     288            this._resourceDataGridNodeMap.set(resource, dataGridNode);
     289        }
     290
     291        if (!dataGridNode.parent) {
     292            let parentFrame = resource.parentFrame;
     293            if (!parentFrame)
    246294                return null;
    247         }
    248 
    249         this._insertDataGridNode(resourceDataGridNode, parentDataGridNode);
    250 
    251         return resourceDataGridNode;
     295
     296            let expandedByDefault = false;
     297            if (parentFrame.mainResource === resource || parentFrame.provisionalMainResource === resource) {
     298                parentFrame = parentFrame.parentFrame;
     299                expandedByDefault = !parentFrame; // Main frame expands by default.
     300            }
     301
     302            if (expandedByDefault)
     303                dataGridNode.expand();
     304
     305            let parentDataGridNode = null;
     306            if (parentFrame) {
     307                // Find the parent main resource, adding it if needed, to append this resource as a child.
     308                let parentResource = parentFrame.provisionalMainResource || parentFrame.mainResource;
     309
     310                parentDataGridNode = this._addResourceToDataGridIfNeeded(parentResource);
     311                console.assert(parentDataGridNode);
     312                if (!parentDataGridNode)
     313                    return null;
     314            }
     315
     316            this._insertDataGridNode(dataGridNode, parentDataGridNode);
     317        }
     318
     319        dataGridNode.refresh();
     320        return dataGridNode;
    252321    }
    253322
    254323    _addSourceCodeTimeline(sourceCodeTimeline)
    255324    {
    256         let parentDataGridNode = sourceCodeTimeline.sourceCodeLocation ? this._addResourceToDataGridIfNeeded(sourceCodeTimeline.sourceCode) : null;
    257         let sourceCodeTimelineDataGridNode = new WI.SourceCodeTimelineTimelineDataGridNode(sourceCodeTimeline, {
    258             graphDataSource: this,
    259         });
    260         this._resourceDataGridNodeMap.set(sourceCodeTimeline, sourceCodeTimelineDataGridNode);
    261 
    262         this._insertDataGridNode(sourceCodeTimelineDataGridNode, parentDataGridNode);
     325        let dataGridNode = this._resourceDataGridNodeMap.get(sourceCodeTimeline);
     326        if (!dataGridNode) {
     327            dataGridNode = new WI.SourceCodeTimelineTimelineDataGridNode(sourceCodeTimeline, {
     328                graphDataSource: this,
     329            });
     330            this._resourceDataGridNodeMap.set(sourceCodeTimeline, dataGridNode);
     331        }
     332
     333        if (!dataGridNode.parent) {
     334            let parentDataGridNode = sourceCodeTimeline.sourceCodeLocation ? this._addResourceToDataGridIfNeeded(sourceCodeTimeline.sourceCode) : null;
     335            this._insertDataGridNode(dataGridNode, parentDataGridNode);
     336        }
    263337    }
    264338
     
    269343
    270344        for (var representedObject of this._pendingRepresentedObjects) {
    271             if (representedObject instanceof WI.Resource)
    272                 this._addResourceToDataGridIfNeeded(representedObject);
    273             else if (representedObject instanceof WI.SourceCodeTimeline)
    274                 this._addSourceCodeTimeline(representedObject);
    275             else
    276                 console.error("Unknown represented object");
     345            if (this._shouldGroupBySourceCode) {
     346                if (representedObject instanceof WI.Resource)
     347                    this._addResourceToDataGridIfNeeded(representedObject);
     348                else if (representedObject instanceof WI.SourceCodeTimeline)
     349                    this._addSourceCodeTimeline(representedObject);
     350                else
     351                    console.error("Unknown represented object", representedObject);
     352            } else {
     353                const options = {
     354                    graphDataSource: this,
     355                    shouldShowPopover: true,
     356                };
     357
     358                let dataGridNode = null;
     359                if (representedObject instanceof WI.ResourceTimelineRecord)
     360                    dataGridNode = new WI.ResourceTimelineDataGridNode(representedObject, options);
     361                else if (representedObject instanceof WI.LayoutTimelineRecord)
     362                    dataGridNode = new WI.LayoutTimelineDataGridNode(representedObject, options);
     363                else if (representedObject instanceof WI.MediaTimelineRecord)
     364                    dataGridNode = new WI.MediaTimelineDataGridNode(representedObject, options);
     365                else if (representedObject instanceof WI.ScriptTimelineRecord)
     366                    dataGridNode = new WI.ScriptTimelineDataGridNode(representedObject, options);
     367                else if (representedObject instanceof WI.HeapAllocationsTimelineRecord)
     368                    dataGridNode = new WI.HeapAllocationsTimelineDataGridNode(representedObject, options);
     369
     370                console.assert(dataGridNode, representedObject);
     371                if (!dataGridNode)
     372                    continue;
     373
     374                let comparator = (a, b) => {
     375                    return a.record.startTime - b.record.startTime;
     376                };
     377
     378                this._dataGrid.insertChild(dataGridNode, insertionIndexForObjectInListSortedByFunction(dataGridNode, this._dataGrid.children, comparator));
     379            }
    277380        }
    278381
     
    280383    }
    281384
    282     _networkTimelineRecordAdded(event)
    283     {
    284         var resourceTimelineRecord = event.data.record;
    285         console.assert(resourceTimelineRecord instanceof WI.ResourceTimelineRecord);
    286 
    287         this._pendingRepresentedObjects.push(resourceTimelineRecord.resource);
     385    _handleGroupBySourceCodeSettingChanged(event)
     386    {
     387        let groupBySourceCode = this._shouldGroupBySourceCode;
     388        this._dataGrid.disclosureColumnIdentifier = groupBySourceCode ? "name" : undefined;
     389        this._dataGrid.setColumnVisible("source", !groupBySourceCode);
     390        if (this._groupBySourceCodeNavigationItem)
     391            this._groupBySourceCodeNavigationItem.checked = groupBySourceCode;
     392
     393        this._loadExistingRecords();
     394    }
     395
     396    _handleGroupBySourceCodeNavigationItemCheckedDidChange(event)
     397    {
     398        WI.settings.timelineOverviewGroupBySourceCode.value = !WI.settings.timelineOverviewGroupBySourceCode.value;
     399    }
     400
     401    _handleTimelineRecordAdded(event)
     402    {
     403        let {record} = event.data;
     404
     405        if (this._shouldGroupBySourceCode) {
     406            if (event.target.type !== WI.TimelineRecord.Type.Network)
     407                return;
     408
     409            console.assert(record instanceof WI.ResourceTimelineRecord);
     410
     411            this._pendingRepresentedObjects.push(record.resource);
     412        } else
     413            this._pendingRepresentedObjects.push(record);
    288414
    289415        this.needsLayout();
    290 
    291         // We don't expect to have any source code timelines yet. Those should be added with _sourceCodeTimelineAdded.
    292         console.assert(!this._recording.sourceCodeTimelinesForSourceCode(resourceTimelineRecord.resource).length);
    293416    }
    294417
    295418    _sourceCodeTimelineAdded(event)
    296419    {
     420        if (!this._shouldGroupBySourceCode)
     421            return;
     422
    297423        var sourceCodeTimeline = event.data.sourceCodeTimeline;
    298424        console.assert(sourceCodeTimeline);
  • trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js

    r243213 r243301  
    7575        this._cachedData.remoteAddress = this.resource.remoteAddress;
    7676        this._cachedData.connectionIdentifier = this.resource.connectionIdentifier;
     77        this._cachedData.initiator = this.resource.initiatorSourceCodeLocation;
    7778        return this._cachedData;
    7879    }
     
    140141                cell.title = title;
    141142            return title || emDash;
     143
     144        case "source": // Timeline Overview
     145            return super.createCellContent("initiator", cell);
    142146        }
    143147
  • trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js

    r243269 r243301  
    7070        this._cachedData.callCount = this.record.callCountOrSamples;
    7171        this._cachedData.location = this.record.initiatorCallFrame || this.record.sourceCodeLocation;
    72 
    7372        return this._cachedData;
    7473    }
     
    8786            else
    8887                this._subtitle = WI.UIString("%s delay").format(timeoutString);
    89         } else if (this._record.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched) {
    90             if (this._record.extraDetails && this._record.extraDetails.defaultPrevented)
     88        } else if (this.record.eventType === WI.ScriptTimelineRecord.EventType.EventDispatched) {
     89            if (this.record.extraDetails && this.record.extraDetails.defaultPrevented)
    9190                this._subtitle = WI.UIString("default prevented");
    9291        }
     
    120119        case "area":
    121120            return zeroWidthSpace;
     121
     122        case "source": // Timeline Overview
     123            return super.createCellContent("location", cell);
    122124        }
    123125
  • trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordBar.css

    r243024 r243301  
    123123}
    124124
    125 .timeline-record-bar.timeline-record-type-script.garbage-collected > .segment {
     125.timeline-record-bar.timeline-record-type-script.garbage-collected > .segment,
     126.timeline-record-bar.timeline-record-type-heap-allocations > .segment {
    126127    background-color: hsl(23, 69%, 73%);
    127128    border-color: hsl(11, 54%, 62%);   
  • trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js

    r243024 r243301  
    8888        this._timelineContentBrowser.addSubview(this._progressView);
    8989
    90         this._importedView = new WI.TimelineRecordingImportedView;
    91         this._timelineContentBrowser.addSubview(this._importedView);
    92 
    9390        this._timelineViewMap = new Map;
    9491        this._pathComponentMap = new Map;
     
    317314        this._updateTimelineOverviewHeight();
    318315        this._updateProgressView();
    319         this._updateImportedView();
    320316        this._updateFilterBar();
    321317
     
    943939    }
    944940
    945     _updateImportedView()
    946     {
    947         this._importedView.visible = this._recording.imported && this.currentTimelineView && this.currentTimelineView.showsImportedRecordingMessage;
    948     }
    949 
    950941    _updateFilterBar()
    951942    {
Note: See TracChangeset for help on using the changeset viewer.