Bug 132073

Summary: Web Inspector: probe sample should be revealed in details sidebar when selected in Timelines panel
Product: WebKit Reporter: Brian Burg <burg>
Component: Web InspectorAssignee: Nobody <webkit-unassigned>
Status: NEW ---    
Severity: Normal CC: graouts, inspector-bugzilla-changes, madonnk, webkit-bug-importer
Priority: P2 Keywords: InRadar
Version: 528+ (Nightly build)   
Hardware: All   
OS: All   
Bug Depends on: 138976    
Bug Blocks: 136292    
Attachments:
Description Flags
Patch
none
Patch
none
Patch joepeck: review-

Description Brian Burg 2014-04-23 13:39:28 PDT
I think the way to go is to add a supplementalRepresentedObject(s) parameter to showSourceCodeLocation(). When called, it will show the source code location, then ask the active toolbars if they can show the supplemental object. In this case, the supplemental object is a WebInspector.ProbeSample or a dummy object with ProbeSet+hitcount. The sidebar can check if the sample is in any of the probe sets and reveal the related ProbeSetDataFrame and its view (table row).
Comment 1 Radar WebKit Bug Importer 2014-04-23 13:40:04 PDT
<rdar://problem/16703731>
Comment 2 Timothy Hatcher 2014-04-23 13:57:05 PDT
Sounds right.
Comment 3 Katie Madonna 2014-06-12 13:25:58 PDT
Created attachment 232977 [details]
Patch
Comment 4 Timothy Hatcher 2014-06-25 12:32:44 PDT
Comment on attachment 232977 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=232977&action=review

WIP patch looks right so far. Planning to finish this up?

> Source/WebInspectorUI/UserInterface/Base/Main.js:1556
> +        console.log(event);

This should be removed in the final patch.

> Source/WebInspectorUI/UserInterface/Views/ResourceSidebarPanel.js:187
> +        if (supplementalRepresentedObject !== undefined) {

No need for the "!== undefined".

> Source/WebInspectorUI/UserInterface/Views/ResourceSidebarPanel.js:195
> +            var currentSidebarPanels = WebInspector.detailsSidebar.sidebarPanels;
> +            for (var sidebarPanel of currentSidebarPanels) {
> +                if (sidebarPanel.inspect(supplementalRepresentedObject))
> +                    console.log("Can show that object");
> +                else
> +                    console.log("Cannot show object");
> +            }
> +        }

You should use WebInspector.sidebarPanelForRepresentedObject to find the right panel. Maybe move this to a helper function to share with the other places that do this.

What will you do with the sidebarPanel once you have it?

> Source/WebInspectorUI/UserInterface/Views/ResourceSidebarPanel.js:202
> +        if (supplementalRepresentedObject !== undefined) {

Ditto.

> Source/WebInspectorUI/UserInterface/Views/ResourceSidebarPanel.js:210
> +            var currentSidebarPanels = WebInspector.detailsSidebar.sidebarPanels;
> +            for (var sidebarPanel of currentSidebarPanels) {
> +                if (sidebarPanel.inspect(supplementalRepresentedObject))
> +                    console.log("Can show that object");
> +                else
> +                    console.log("Cannot show object");
> +            }
> +        }

Ditto.

> Source/WebInspectorUI/UserInterface/Views/ResourceSidebarPanel.js:217
> +        if (supplementalRepresentedObject !== undefined) {

Ditto.

> Source/WebInspectorUI/UserInterface/Views/ResourceSidebarPanel.js:224
> +            var currentSidebarPanels = WebInspector.detailsSidebar.sidebarPanels;
> +            for (var sidebarPanel of currentSidebarPanels) {
> +                if (sidebarPanel.inspect(supplementalRepresentedObject))
> +                    console.log("Can show that object");
> +                else
> +                    console.log("Cannot show object");
> +            }

Ditto.

> Source/WebInspectorUI/UserInterface/Views/ScriptTimelineView.js:278
> +        console.log(treeElement.representedObject);

This should be removed.
Comment 5 Brian Burg 2014-06-27 14:32:27 PDT
Katie is gone for the summer. I will finish off this patch on the weekend or Monday.
Comment 6 Katie Madonna 2014-12-05 18:20:26 PST
Created attachment 242692 [details]
Patch
Comment 7 Joseph Pecoraro 2014-12-09 11:17:54 PST
Comment on attachment 242692 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=242692&action=review

> Source/WebInspectorUI/UserInterface/Base/Main.js:407
> +    if (representedObject && representedObject.eventType === WebInspector.ScriptTimelineRecord.EventType.ProbeSampleRecorded)
> +        return this.probeDetailsSidebarPanel;

I would feel safer with stricter type checks since this is in the generic namespace and "object" could be anything.. Something like:

    if (!representedObject)
        return null;
    if (representedObject instanceof WebInspector.ScriptTimelineRecord) {
        if (representedObject.eventType === WebInspector.ScriptTimelineRecord.EventType.ProbeSampleRecorded)
            return this.probeDetailsSidebarPanel;
    }
    return null;

That said, it isn't always possible to narrow down a specific representedObject to a single detailsSidebarPanel. For example, a WebInspector.DOMNode is associated with the Styles/Node/LayerTree details sidebars. So I'm not sure this is the right solution.

> Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js:350
> +                var details = {
> +                    "probeId": recordPayload.data.probeId,
> +                    "sampleId": recordPayload.data.sampleId
> +                };
> +
>                  // Pass the startTime as the endTime since this record type has no duration.
>                  sourceCodeLocation = WebInspector.probeManager.probeForIdentifier(recordPayload.data.probeId).breakpoint.sourceCodeLocation;
> -                this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.ProbeSampleRecorded, startTime, startTime, callFrames, sourceCodeLocation, recordPayload.data.probeId));
> +                this._addRecord(new WebInspector.ScriptTimelineRecord(WebInspector.ScriptTimelineRecord.EventType.ProbeSampleRecorded, startTime, startTime, callFrames, sourceCodeLocation, details));

How about just passing recordPayload.data and not making the duplicate temp object.

> Source/WebInspectorUI/UserInterface/Views/DetailsSidebarPanel.js:81
> +    reveal: function(objects)

What is "objects"? Usage seems to be a single represented object. Perhaps this should just be "object"?

> Source/WebInspectorUI/UserInterface/Views/ProbeDetailsSidebarPanel.js:100
> +    reveal: function(objects)
> +    {
> +        var probeId = objects.details.probeId;

This feels dangerous you are assuming the passed object has some properties. You should assert and bail if it is not an expected type. (instanceof check).

> Source/WebInspectorUI/UserInterface/Views/ProbeDetailsSidebarPanel.js:103
> +            return probeSet.probes.findIndex(function (probe) { return probe.id === probeId; }) !== -1;

Style: "function (probe)" => "function(probe)"

> Source/WebInspectorUI/UserInterface/Views/ProbeSetDataGrid.js:83
> +        node.element.classList.add(WebInspector.ProbeSetDataGrid.HighlightedFrameStyleClassName);
> +        window.setTimeout(function() {
> +            node.element.classList.remove(WebInspector.ProbeSetDataGrid.HighlightedFrameStyleClassName);
> +        }, WebInspector.ProbeSetDataGrid.DataUpdatedAnimationDuration);
> +    },

Style: "window.setTimeout" => "setTimeout"

Should this handle multiple animations gracefully? Something like:

    if (this._blinkTimeoutIdentifier)
        clearTimeout(this._blinkTimeoutIdentifier);
    this._blinkTimeoutIdentifier = setTimeout(function() { ... }, WebInspector.ProbeSetDataGrid.DataUpdatedAnimationDuration);

> Source/WebInspectorUI/UserInterface/Views/ProbeSetDetailsSection.js:90
> +        var selectedFrame = this._probeSet.dataTable.frames.find(function (frame) { return frame[probeId].sampleId === sampleId; });

Style: "function (frame)" => "function(frame)"
Comment 8 Katie Madonna 2014-12-12 20:44:09 PST
Created attachment 243244 [details]
Patch
Comment 9 Joseph Pecoraro 2014-12-16 11:54:26 PST
Comment on attachment 243244 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=243244&action=review

This patch is certainly much better, but now that I think about it some more, I think we may want to change how this works.

Details sidebars should automatically show based on whatever is selected. As is the case for selecting a Resource in the timeline. Therefore the Probe sidebar should automatically show when selecting a probe timeline record. If the sidebar is forced to show (like this), then what determines when it should hide or how it will stay shown?

The existing mechanism hooks are having the ContentView change its path components or triggering a SupplementalRepresentedObjectsDidChange event. You could make the ScriptTimelineRecord / ProbeSet / Probe a supplemental representedObject and trigger the event. Then make sure that ProbeDetailsSidebarPanel.prototype.inspect recognizes it, and determines that it should show it.

Does that sound good?

> Source/WebInspectorUI/UserInterface/Views/ProbeDetailsSidebarPanel.js:110
> +            return probeSet.probes.findIndex(function(probe) { return probe.id === probeId; }) !== -1;

Seems this inner could just be another find, thereby avoiding the comparison to -1.

> Source/WebInspectorUI/UserInterface/Views/ProbeSetDataGrid.js:85
> +            node.element.classList.remove(WebInspector.ProbeSetDataGrid.HighlightedFrameStyleClassName);

Insider here you should:

    delete this._blinkTimeoutIdentifier;

> Source/WebInspectorUI/UserInterface/Views/ProbeSetDetailsSection.js:90
> +        var selectedFrame = this._probeSet.dataTable.frames.find(function(frame) { return frame[probeId].sampleId === sampleId; });

Is frame[probeId] guarenteed to exist?

> Source/WebInspectorUI/UserInterface/Views/ScriptTimelineView.js:285
> +
> +

Nit: Extra newline.
Comment 10 Timothy Hatcher 2014-12-17 06:08:27 PST
(In reply to comment #9)
> Comment on attachment 243244 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=243244&action=review
> 
> This patch is certainly much better, but now that I think about it some
> more, I think we may want to change how this works.
> 
> Details sidebars should automatically show based on whatever is selected. As
> is the case for selecting a Resource in the timeline. Therefore the Probe
> sidebar should automatically show when selecting a probe timeline record. If
> the sidebar is forced to show (like this), then what determines when it
> should hide or how it will stay shown?
> 
> The existing mechanism hooks are having the ContentView change its path
> components or triggering a SupplementalRepresentedObjectsDidChange event.
> You could make the ScriptTimelineRecord / ProbeSet / Probe a supplemental
> representedObject and trigger the event. Then make sure that
> ProbeDetailsSidebarPanel.prototype.inspect recognizes it, and determines
> that it should show it.
> 
> Does that sound good?

That is the correct approach. SupplementalRepresentedObjectsDidChange can force the details sidebar open, if it was open before and it had to close automatically because it became empty (from switching views, etc.)

This would be similar to how ScopeChainDetailsSidebar works and how TextResourceContentView and ScriptContentView puts the active CallFrame into the array in the supplementalRepresentedObjects getter.