d684499516eb22b3b6071c816df3a67ecaa54334
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / ScriptClusterTimelineView.js
1 /*
2  * Copyright (C) 2016 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WebInspector.ScriptClusterTimelineView = class ScriptClusterTimelineView extends WebInspector.ClusterContentView
27 {
28     constructor(timeline, extraArguments)
29     {
30         super(timeline);
31
32         console.assert(timeline.type === WebInspector.TimelineRecord.Type.Script);
33
34         this._currentContentViewSetting = new WebInspector.Setting("script-cluster-timeline-view-current-view", WebInspector.ScriptClusterTimelineView.EventsIdentifier);
35
36         let showSelectorArrows = this._canShowProfileView();
37         function createPathComponent(displayName, className, identifier)
38         {
39             let pathComponent = new WebInspector.HierarchicalPathComponent(displayName, className, identifier, false, showSelectorArrows);
40             pathComponent.addEventListener(WebInspector.HierarchicalPathComponent.Event.SiblingWasSelected, this._pathComponentSelected, this);
41             return pathComponent;
42         }
43
44         this._eventsPathComponent = createPathComponent.call(this, WebInspector.UIString("Events"), "events-icon", WebInspector.ScriptClusterTimelineView.EventsIdentifier);
45         this._profilePathComponent = createPathComponent.call(this, WebInspector.UIString("Call Trees"), "call-trees-icon", WebInspector.ScriptClusterTimelineView.ProfileIdentifier);
46
47         if (this._canShowProfileView()) {
48             this._eventsPathComponent.nextSibling = this._profilePathComponent;
49             this._profilePathComponent.previousSibling = this._eventsPathComponent;
50         }
51
52         // FIXME: We should be able to create these lazily.
53         this._eventsContentView = new WebInspector.ScriptDetailsTimelineView(this.representedObject, extraArguments);
54         this._profileContentView = this._canShowProfileView() ? new WebInspector.ScriptProfileTimelineView(this.representedObject, extraArguments) : null;
55
56         this._showContentViewForIdentifier(this._currentContentViewSetting.value);
57
58         this.contentViewContainer.addEventListener(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange, this._scriptClusterViewCurrentContentViewDidChange, this)
59     }
60
61     // TimelineView
62
63     // FIXME: Determine a better way to bridge TimelineView methods to the sub-timeline views.
64     get showsLiveRecordingData() { return this._contentViewContainer.currentContentView.showsLiveRecordingData; }
65     get showsFilterBar() { return this._contentViewContainer.currentContentView.showsFilterBar; }
66     get zeroTime() { return this._contentViewContainer.currentContentView.zeroTime; }
67     set zeroTime(x) { this._contentViewContainer.currentContentView.zeroTime = x; }
68     get startTime() { return this._contentViewContainer.currentContentView.startTime; }
69     set startTime(x) { this._contentViewContainer.currentContentView.startTime = x; }
70     get endTime() { return this._contentViewContainer.currentContentView.endTime; }
71     set endTime(x) { this._contentViewContainer.currentContentView.endTime = x; }
72     get currentTime() { return this._contentViewContainer.currentContentView.currentTime; }
73     set currentTime(x) { this._contentViewContainer.currentContentView.currentTime = x; }
74     get scrollableElements() { return this._contentViewContainer.currentContentView.scrollableElements; }
75     selectRecord(record) { this._contentViewContainer.currentContentView.selectRecord(record); }
76     updateFilter(filters) { return this._contentViewContainer.currentContentView.updateFilter(filters); }
77     filterDidChange() { return this._contentViewContainer.currentContentView.filterDidChange(); }
78     matchDataGridNodeAgainstCustomFilters(node) { return this._contentViewContainer.currentContentView.matchDataGridNodeAgainstCustomFilters(node); }
79
80     reset()
81     {
82         this._eventsContentView.reset();
83
84         if (this._profileContentView)
85             this._profileContentView.reset();
86     }
87
88     // Public
89
90     get eventsContentView()
91     {
92         return this._eventsContentView;
93     }
94
95     get profileContentView()
96     {
97         return this._profileContentView;
98     }
99
100     get selectionPathComponents()
101     {
102         let currentContentView = this._contentViewContainer.currentContentView;
103         if (!currentContentView)
104             return [];
105
106         let components = [this._pathComponentForContentView(currentContentView)];
107         let subComponents = currentContentView.selectionPathComponents;
108         if (subComponents)
109             return components.concat(subComponents);
110         return components;
111     }
112
113     saveToCookie(cookie)
114     {
115         cookie[WebInspector.ScriptClusterTimelineView.ContentViewIdentifierCookieKey] = this._currentContentViewSetting.value;
116     }
117
118     restoreFromCookie(cookie)
119     {
120         this._showContentViewForIdentifier(cookie[WebInspector.ScriptClusterTimelineView.ContentViewIdentifierCookieKey]);
121     }
122
123     showEvents()
124     {
125         return this._showContentViewForIdentifier(WebInspector.ScriptClusterTimelineView.EventsIdentifier);
126     }
127
128     showProfile()
129     {
130         if (!this._canShowProfileView())
131             return this.showEvents();
132
133         return this._showContentViewForIdentifier(WebInspector.ScriptClusterTimelineView.ProfileIdentifier);
134     }
135
136     // Private
137
138     _canShowProfileView()
139     {
140         // COMPATIBILITY (iOS 9): Legacy backends did not include CallingContextTree ScriptProfiler data.
141         return window.ScriptProfilerAgent;
142     }
143
144     _pathComponentForContentView(contentView)
145     {
146         console.assert(contentView);
147         if (!contentView)
148             return null;
149         if (contentView === this._eventsContentView)
150             return this._eventsPathComponent;
151         if (contentView === this._profileContentView)
152             return this._profilePathComponent;
153         console.error("Unknown contentView.");
154         return null;
155     }
156
157     _identifierForContentView(contentView)
158     {
159         console.assert(contentView);
160         if (!contentView)
161             return null;
162         if (contentView === this._eventsContentView)
163             return WebInspector.ScriptClusterTimelineView.EventsIdentifier;
164         if (contentView === this._profileContentView)
165             return WebInspector.ScriptClusterTimelineView.ProfileIdentifier;
166         console.error("Unknown contentView.");
167         return null;
168     }
169
170     _showContentViewForIdentifier(identifier)
171     {
172         let contentViewToShow = null;
173
174         switch (identifier) {
175         case WebInspector.ScriptClusterTimelineView.EventsIdentifier:
176             contentViewToShow = this.eventsContentView;
177             break;
178         case WebInspector.ScriptClusterTimelineView.ProfileIdentifier:
179             contentViewToShow = this.profileContentView;
180             break;
181         }
182
183         if (!contentViewToShow)
184             contentViewToShow = this.eventsContentView;
185
186         console.assert(contentViewToShow);
187
188         this._currentContentViewSetting.value = this._identifierForContentView(contentViewToShow);
189
190         return this.contentViewContainer.showContentView(contentViewToShow);
191     }
192
193     _pathComponentSelected(event)
194     {
195         this._showContentViewForIdentifier(event.data.pathComponent.representedObject);
196     }
197
198     _scriptClusterViewCurrentContentViewDidChange(event)
199     {
200         let currentContentView = this._contentViewContainer.currentContentView;
201         if (!currentContentView)
202             return;
203
204         let previousContentView = currentContentView === this._eventsContentView ? this._profileContentView : this._eventsContentView;
205
206         currentContentView.zeroTime = previousContentView.zeroTime;
207         currentContentView.startTime = previousContentView.startTime;
208         currentContentView.endTime = previousContentView.endTime;
209         currentContentView.currentTime = previousContentView.currentTime;
210     }
211 };
212
213 WebInspector.ScriptClusterTimelineView.ContentViewIdentifierCookieKey = "script-cluster-timeline-view-identifier";
214
215 WebInspector.ScriptClusterTimelineView.EventsIdentifier = "events";
216 WebInspector.ScriptClusterTimelineView.ProfileIdentifier = "profile";