Web Inspector: Show rendering frames (and FPS) in Layout and Rendering timeline
[WebKit-https.git] / Source / WebCore / inspector / InspectorTimelineAgent.h
1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * Copyright (C) 2014 University of Washington.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 *     * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 *     * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #ifndef InspectorTimelineAgent_h
33 #define InspectorTimelineAgent_h
34
35 #include "InspectorWebAgentBase.h"
36 #include "LayoutRect.h"
37 #include <inspector/InspectorBackendDispatchers.h>
38 #include <inspector/InspectorFrontendDispatchers.h>
39 #include <inspector/InspectorValues.h>
40 #include <inspector/ScriptDebugListener.h>
41 #include <wtf/Stopwatch.h>
42 #include <wtf/Vector.h>
43 #include <wtf/WeakPtr.h>
44
45 namespace JSC {
46 class Profile;
47 }
48
49 namespace WebCore {
50
51 class Event;
52 class FloatQuad;
53 class Frame;
54 class InspectorClient;
55 class InspectorPageAgent;
56 class InstrumentingAgents;
57 class IntRect;
58 class URL;
59 class Page;
60 class PageScriptDebugServer;
61 class RenderObject;
62 class ResourceRequest;
63 class ResourceResponse;
64 class RunLoopObserver;
65
66 typedef String ErrorString;
67
68 enum class TimelineRecordType {
69     EventDispatch,
70     ScheduleStyleRecalculation,
71     RecalculateStyles,
72     InvalidateLayout,
73     Layout,
74     Paint,
75     RunLoop,
76     ScrollLayer,
77
78     ParseHTML,
79
80     TimerInstall,
81     TimerRemove,
82     TimerFire,
83
84     EvaluateScript,
85
86     MarkLoad,
87     MarkDOMContent,
88
89     TimeStamp,
90     Time,
91     TimeEnd,
92
93     XHRReadyStateChange,
94     XHRLoad,
95
96     FunctionCall,
97     ProbeSample,
98     ConsoleProfile,
99
100     RequestAnimationFrame,
101     CancelAnimationFrame,
102     FireAnimationFrame,
103
104     WebSocketCreate,
105     WebSocketSendHandshakeRequest,
106     WebSocketReceiveHandshakeResponse,
107     WebSocketDestroy
108 };
109
110 class InspectorTimelineAgent final
111     : public InspectorAgentBase
112     , public Inspector::TimelineBackendDispatcherHandler
113     , public Inspector::ScriptDebugListener {
114     WTF_MAKE_NONCOPYABLE(InspectorTimelineAgent);
115     WTF_MAKE_FAST_ALLOCATED;
116 public:
117     enum InspectorType { PageInspector, WorkerInspector };
118
119     InspectorTimelineAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorType, InspectorClient*);
120     virtual ~InspectorTimelineAgent();
121
122     virtual void didCreateFrontendAndBackend(Inspector::FrontendChannel*, Inspector::BackendDispatcher*) override;
123     virtual void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override;
124
125     virtual void start(ErrorString&, const int* maxCallStackDepth = nullptr) override;
126     virtual void stop(ErrorString&) override;
127
128     int id() const { return m_id; }
129
130     void setPageScriptDebugServer(PageScriptDebugServer*);
131
132     void didCommitLoad();
133
134     // Methods called from WebCore.
135     void startFromConsole(JSC::ExecState*, const String &title);
136     PassRefPtr<JSC::Profile> stopFromConsole(JSC::ExecState*, const String& title);
137
138     // InspectorInstrumentation callbacks.
139     void didInstallTimer(int timerId, int timeout, bool singleShot, Frame*);
140     void didRemoveTimer(int timerId, Frame*);
141     void willFireTimer(int timerId, Frame*);
142     void didFireTimer();
143     void willCallFunction(const String& scriptName, int scriptLine, Frame*);
144     void didCallFunction(Frame*);
145     void willDispatchXHRReadyStateChangeEvent(const String&, int, Frame*);
146     void didDispatchXHRReadyStateChangeEvent();
147     void willDispatchEvent(const Event&, Frame*);
148     void didDispatchEvent();
149     void willEvaluateScript(const String&, int, Frame&);
150     void didEvaluateScript(Frame&);
151     void didInvalidateLayout(Frame&);
152     void willLayout(Frame&);
153     void didLayout(RenderObject*);
154     void willScroll(Frame&);
155     void didScroll();
156     void willDispatchXHRLoadEvent(const String&, Frame*);
157     void didDispatchXHRLoadEvent();
158     void willPaint(Frame&);
159     void didPaint(RenderObject*, const LayoutRect&);
160     void willRecalculateStyle(Frame*);
161     void didRecalculateStyle();
162     void didScheduleStyleRecalculation(Frame*);
163     void willWriteHTML(unsigned startLine, Frame*);
164     void didWriteHTML(unsigned endLine);
165     void didTimeStamp(Frame&, const String&);
166     void didMarkDOMContentEvent(Frame&);
167     void didMarkLoadEvent(Frame&);
168     void didRequestAnimationFrame(int callbackId, Frame*);
169     void didCancelAnimationFrame(int callbackId, Frame*);
170     void willFireAnimationFrame(int callbackId, Frame*);
171     void didFireAnimationFrame();
172     void time(Frame&, const String&);
173     void timeEnd(Frame&, const String&);
174 #if ENABLE(WEB_SOCKETS)
175     void didCreateWebSocket(unsigned long identifier, const URL&, const String& protocol, Frame*);
176     void willSendWebSocketHandshakeRequest(unsigned long identifier, Frame*);
177     void didReceiveWebSocketHandshakeResponse(unsigned long identifier, Frame*);
178     void didDestroyWebSocket(unsigned long identifier, Frame*);
179 #endif
180
181 protected:
182     // ScriptDebugListener
183     virtual void didParseSource(JSC::SourceID, const Script&) override { }
184     virtual void failedToParseSource(const String&, const String&, int, int, const String&) override { }
185     virtual void didPause(JSC::ExecState*, const Deprecated::ScriptValue&, const Deprecated::ScriptValue&) override { }
186     virtual void didContinue() override { }
187
188     virtual void breakpointActionLog(JSC::ExecState*, const String&) override { }
189     virtual void breakpointActionSound(int) override { }
190     virtual void breakpointActionProbe(JSC::ExecState*, const Inspector::ScriptBreakpointAction&, unsigned batchId, unsigned sampleId, const Deprecated::ScriptValue& result) override;
191
192 private:
193     friend class TimelineRecordStack;
194
195     struct TimelineRecordEntry {
196         TimelineRecordEntry()
197             : type(TimelineRecordType::EventDispatch) { }
198         TimelineRecordEntry(PassRefPtr<Inspector::InspectorObject> record, PassRefPtr<Inspector::InspectorObject> data, PassRefPtr<Inspector::InspectorArray> children, TimelineRecordType type)
199             : record(record), data(data), children(children), type(type)
200         {
201         }
202
203         RefPtr<Inspector::InspectorObject> record;
204         RefPtr<Inspector::InspectorObject> data;
205         RefPtr<Inspector::InspectorArray> children;
206         TimelineRecordType type;
207     };
208
209     void internalStart(const int* maxCallStackDepth = nullptr);
210     void internalStop();
211     double timestamp();
212
213     void sendEvent(RefPtr<Inspector::InspectorObject>&&);
214     void appendRecord(RefPtr<Inspector::InspectorObject>&& data, TimelineRecordType, bool captureCallStack, Frame*);
215     void pushCurrentRecord(RefPtr<Inspector::InspectorObject>&&, TimelineRecordType, bool captureCallStack, Frame*);
216     void pushCurrentRecord(const TimelineRecordEntry& record) { m_recordStack.append(record); }
217
218     TimelineRecordEntry createRecordEntry(RefPtr<Inspector::InspectorObject>&& data, TimelineRecordType, bool captureCallStack, Frame*);
219
220     void setFrameIdentifier(Inspector::InspectorObject* record, Frame*);
221
222     void didCompleteRecordEntry(const TimelineRecordEntry&);
223     void didCompleteCurrentRecord(TimelineRecordType);
224
225     void addRecordToTimeline(RefPtr<Inspector::InspectorObject>&&, TimelineRecordType);
226     void clearRecordStack();
227
228     void localToPageQuad(const RenderObject&, const LayoutRect&, FloatQuad*);
229     Page* page();
230
231     InspectorPageAgent* m_pageAgent;
232     PageScriptDebugServer* m_scriptDebugServer;
233
234     std::unique_ptr<Inspector::TimelineFrontendDispatcher> m_frontendDispatcher;
235     RefPtr<Inspector::TimelineBackendDispatcher> m_backendDispatcher;
236
237     Vector<TimelineRecordEntry> m_recordStack;
238
239     int m_id;
240     int m_callStackDepth;
241     int m_maxCallStackDepth;
242     InspectorType m_inspectorType;
243     InspectorClient* m_client;
244
245     Vector<TimelineRecordEntry> m_pendingConsoleProfileRecords;
246
247     bool m_enabled;
248     bool m_enabledFromFrontend;
249
250 #if PLATFORM(COCOA)
251     std::unique_ptr<WebCore::RunLoopObserver> m_frameStartObserver;
252     std::unique_ptr<WebCore::RunLoopObserver> m_frameStopObserver;
253 #endif
254     bool m_didStartRecordingRunLoop;
255 };
256
257 } // namespace WebCore
258
259 #endif // !defined(InspectorTimelineAgent_h)