6c41787ca7e43b662bfb4fbefca9869fa15d10a2
[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 zeroTime() { return this._contentViewContainer.currentContentView.zeroTime; }
65     set zeroTime(x) { this._contentViewContainer.currentContentView.zeroTime = x; }
66     get startTime() { return this._contentViewContainer.currentContentView.startTime; }
67     set startTime(x) { this._contentViewContainer.currentContentView.startTime = x; }
68     get endTime() { return this._contentViewContainer.currentContentView.endTime; }
69     set endTime(x) { this._contentViewContainer.currentContentView.endTime = x; }
70     get currentTime() { return this._contentViewContainer.currentContentView.currentTime; }
71     set currentTime(x) { this._contentViewContainer.currentContentView.currentTime = x; }
72     get navigationSidebarTreeOutline() { return this._contentViewContainer.currentContentView.navigationSidebarTreeOutline; }
73     reset() { return this._contentViewContainer.currentContentView.reset(); }
74     filterDidChange() { return this._contentViewContainer.currentContentView.filterDidChange(); }
75     matchTreeElementAgainstCustomFilters(treeElement) { return this._contentViewContainer.currentContentView.matchTreeElementAgainstCustomFilters(treeElement); }
76
77     // Public
78
79     get eventsContentView()
80     {
81         return this._eventsContentView;
82     }
83
84     get profileContentView()
85     {
86         return this._profileContentView;
87     }
88
89     get selectionPathComponents()
90     {
91         let currentContentView = this._contentViewContainer.currentContentView;
92         if (!currentContentView)
93             return [];
94
95         let components = [this._pathComponentForContentView(currentContentView)];
96         let subComponents = currentContentView.selectionPathComponents;
97         if (subComponents)
98             return components.concat(subComponents);
99         return components;
100     }
101
102     saveToCookie(cookie)
103     {
104         cookie[WebInspector.ScriptClusterTimelineView.ContentViewIdentifierCookieKey] = this._currentContentViewSetting.value;
105     }
106
107     restoreFromCookie(cookie)
108     {
109         this._showContentViewForIdentifier(cookie[WebInspector.ScriptClusterTimelineView.ContentViewIdentifierCookieKey]);
110     }
111
112     showEvents()
113     {
114         return this._showContentViewForIdentifier(WebInspector.ScriptClusterTimelineView.EventsIdentifier);
115     }
116
117     showProfile()
118     {
119         if (!this._canShowProfileView())
120             return this.showEvents();
121
122         return this._showContentViewForIdentifier(WebInspector.ScriptClusterTimelineView.ProfileIdentifier);
123     }
124
125     // Private
126
127     _canShowProfileView()
128     {
129         // COMPATIBILITY (iOS 9): Legacy backends did not include CallingContextTree ScriptProfiler data.
130         return window.ScriptProfilerAgent;
131     }
132
133     _pathComponentForContentView(contentView)
134     {
135         console.assert(contentView);
136         if (!contentView)
137             return null;
138         if (contentView === this._eventsContentView)
139             return this._eventsPathComponent;
140         if (contentView === this._profileContentView)
141             return this._profilePathComponent;
142         console.error("Unknown contentView.");
143         return null;
144     }
145
146     _identifierForContentView(contentView)
147     {
148         console.assert(contentView);
149         if (!contentView)
150             return null;
151         if (contentView === this._eventsContentView)
152             return WebInspector.ScriptClusterTimelineView.EventsIdentifier;
153         if (contentView === this._profileContentView)
154             return WebInspector.ScriptClusterTimelineView.ProfileIdentifier;
155         console.error("Unknown contentView.");
156         return null;
157     }
158
159     _showContentViewForIdentifier(identifier)
160     {
161         let contentViewToShow = null;
162
163         switch (identifier) {
164         case WebInspector.ScriptClusterTimelineView.EventsIdentifier:
165             contentViewToShow = this.eventsContentView;
166             break;
167         case WebInspector.ScriptClusterTimelineView.ProfileIdentifier:
168             contentViewToShow = this.profileContentView;
169             break;
170         }
171
172         if (!contentViewToShow)
173             contentViewToShow = this.eventsContentView;
174
175         console.assert(contentViewToShow);
176
177         this._currentContentViewSetting.value = this._identifierForContentView(contentViewToShow);
178
179         return this.contentViewContainer.showContentView(contentViewToShow);
180     }
181
182     _pathComponentSelected(event)
183     {
184         this._showContentViewForIdentifier(event.data.pathComponent.representedObject);
185     }
186
187     _scriptClusterViewCurrentContentViewDidChange(event)
188     {
189         let currentContentView = this._contentViewContainer.currentContentView;
190         if (!currentContentView)
191             return;
192
193         let previousContentView = currentContentView === this._eventsContentView ? this._profileContentView : this._eventsContentView;
194
195         currentContentView.zeroTime = previousContentView.zeroTime;
196         currentContentView.startTime = previousContentView.startTime;
197         currentContentView.endTime = previousContentView.endTime;
198         currentContentView.currentTime = previousContentView.currentTime;
199
200         // FIXME: <https://webkit.org/b/154924> Web Inspector: hook up grid row filtering in the new Timelines UI
201     }
202 };
203
204 WebInspector.ScriptClusterTimelineView.ContentViewIdentifierCookieKey = "script-cluster-timeline-view-identifier";
205
206 WebInspector.ScriptClusterTimelineView.EventsIdentifier = "events";
207 WebInspector.ScriptClusterTimelineView.ProfileIdentifier = "profile";