ebc7d7ffbab698be6e4c0210912eaa98cd5e29ad
[WebKit-https.git] / Source / WebCore / inspector / TimelineRecordFactory.cpp
1 /*
2  * Copyright (C) 2009 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 #include "config.h"
33 #include "TimelineRecordFactory.h"
34
35 #include "Event.h"
36 #include "FloatQuad.h"
37 #include "IntRect.h"
38 #include "JSMainThreadExecState.h"
39 #include "LayoutRect.h"
40 #include "ResourceRequest.h"
41 #include "ResourceResponse.h"
42 #include <inspector/InspectorProtocolObjects.h>
43 #include <inspector/ScriptBreakpoint.h>
44 #include <inspector/ScriptCallStack.h>
45 #include <inspector/ScriptCallStackFactory.h>
46 #include <profiler/Profile.h>
47
48 using namespace Inspector;
49
50 namespace WebCore {
51
52 Ref<InspectorObject> TimelineRecordFactory::createGenericRecord(double startTime, int maxCallStackDepth)
53 {
54     Ref<InspectorObject> record = InspectorObject::create();
55     record->setDouble("startTime", startTime);
56
57     if (maxCallStackDepth) {
58         RefPtr<ScriptCallStack> stackTrace = createScriptCallStack(JSMainThreadExecState::currentState(), maxCallStackDepth);
59         if (stackTrace && stackTrace->size())
60             record->setValue("stackTrace", stackTrace->buildInspectorArray());
61     }
62     return WTF::move(record);
63 }
64
65 Ref<InspectorObject> TimelineRecordFactory::createBackgroundRecord(double startTime, const String& threadName)
66 {
67     Ref<InspectorObject> record = InspectorObject::create();
68     record->setDouble("startTime", startTime);
69     record->setString("thread", threadName);
70     return WTF::move(record);
71 }
72
73 Ref<InspectorObject> TimelineRecordFactory::createGCEventData(const size_t usedHeapSizeDelta)
74 {
75     Ref<InspectorObject> data = InspectorObject::create();
76     data->setInteger("usedHeapSizeDelta", usedHeapSizeDelta);
77     return WTF::move(data);
78 }
79
80 Ref<InspectorObject> TimelineRecordFactory::createFunctionCallData(const String& scriptName, int scriptLine)
81 {
82     Ref<InspectorObject> data = InspectorObject::create();
83     data->setString("scriptName", scriptName);
84     data->setInteger("scriptLine", scriptLine);
85     return WTF::move(data);
86 }
87
88 Ref<InspectorObject> TimelineRecordFactory::createConsoleProfileData(const String& title)
89 {
90     Ref<InspectorObject> data = InspectorObject::create();
91     data->setString("title", title);
92     return WTF::move(data);
93 }
94
95 Ref<InspectorObject> TimelineRecordFactory::createProbeSampleData(const ScriptBreakpointAction& action, unsigned sampleId)
96 {
97     Ref<InspectorObject> data = InspectorObject::create();
98     data->setInteger(ASCIILiteral("probeId"), action.identifier);
99     data->setInteger(ASCIILiteral("sampleId"), sampleId);
100     return WTF::move(data);
101 }
102
103 Ref<InspectorObject> TimelineRecordFactory::createEventDispatchData(const Event& event)
104 {
105     Ref<InspectorObject> data = InspectorObject::create();
106     data->setString("type", event.type().string());
107     return WTF::move(data);
108 }
109
110 Ref<InspectorObject> TimelineRecordFactory::createGenericTimerData(int timerId)
111 {
112     Ref<InspectorObject> data = InspectorObject::create();
113     data->setInteger("timerId", timerId);
114     return WTF::move(data);
115 }
116
117 Ref<InspectorObject> TimelineRecordFactory::createTimerInstallData(int timerId, int timeout, bool singleShot)
118 {
119     Ref<InspectorObject> data = InspectorObject::create();
120     data->setInteger("timerId", timerId);
121     data->setInteger("timeout", timeout);
122     data->setBoolean("singleShot", singleShot);
123     return WTF::move(data);
124 }
125
126 Ref<InspectorObject> TimelineRecordFactory::createXHRReadyStateChangeData(const String& url, int readyState)
127 {
128     Ref<InspectorObject> data = InspectorObject::create();
129     data->setString("url", url);
130     data->setInteger("readyState", readyState);
131     return WTF::move(data);
132 }
133
134 Ref<InspectorObject> TimelineRecordFactory::createXHRLoadData(const String& url)
135 {
136     Ref<InspectorObject> data = InspectorObject::create();
137     data->setString("url", url);
138     return WTF::move(data);
139 }
140
141 Ref<InspectorObject> TimelineRecordFactory::createEvaluateScriptData(const String& url, double lineNumber)
142 {
143     Ref<InspectorObject> data = InspectorObject::create();
144     data->setString("url", url);
145     data->setInteger("lineNumber", lineNumber);
146     return WTF::move(data);
147 }
148
149 Ref<InspectorObject> TimelineRecordFactory::createTimeStampData(const String& message)
150 {
151     Ref<InspectorObject> data = InspectorObject::create();
152     data->setString("message", message);
153     return WTF::move(data);
154 }
155
156 Ref<InspectorObject> TimelineRecordFactory::createLayoutData(unsigned dirtyObjects, unsigned totalObjects, bool partialLayout)
157 {
158     Ref<InspectorObject> data = InspectorObject::create();
159     data->setInteger("dirtyObjects", dirtyObjects);
160     data->setInteger("totalObjects", totalObjects);
161     data->setBoolean("partialLayout", partialLayout);
162     return WTF::move(data);
163 }
164
165 Ref<InspectorObject> TimelineRecordFactory::createMarkData(bool isMainFrame)
166 {
167     Ref<InspectorObject> data = InspectorObject::create();
168     data->setBoolean("isMainFrame", isMainFrame);
169     return WTF::move(data);
170 }
171
172 Ref<InspectorObject> TimelineRecordFactory::createParseHTMLData(unsigned startLine)
173 {
174     Ref<InspectorObject> data = InspectorObject::create();
175     data->setInteger("startLine", startLine);
176     return WTF::move(data);
177 }
178
179 Ref<InspectorObject> TimelineRecordFactory::createAnimationFrameData(int callbackId)
180 {
181     Ref<InspectorObject> data = InspectorObject::create();
182     data->setInteger("id", callbackId);
183     return WTF::move(data);
184 }
185
186 static Ref<InspectorArray> createQuad(const FloatQuad& quad)
187 {
188     Ref<InspectorArray> array = InspectorArray::create();
189     array->pushDouble(quad.p1().x());
190     array->pushDouble(quad.p1().y());
191     array->pushDouble(quad.p2().x());
192     array->pushDouble(quad.p2().y());
193     array->pushDouble(quad.p3().x());
194     array->pushDouble(quad.p3().y());
195     array->pushDouble(quad.p4().x());
196     array->pushDouble(quad.p4().y());
197     return WTF::move(array);
198 }
199
200 Ref<InspectorObject> TimelineRecordFactory::createPaintData(const FloatQuad& quad)
201 {
202     Ref<InspectorObject> data = InspectorObject::create();
203     data->setArray("clip", createQuad(quad));
204     return WTF::move(data);
205 }
206
207 void TimelineRecordFactory::appendLayoutRoot(InspectorObject* data, const FloatQuad& quad)
208 {
209     data->setArray("root", createQuad(quad));
210 }
211
212 static Ref<Protocol::Timeline::CPUProfileNodeAggregateCallInfo> buildAggregateCallInfoInspectorObject(const JSC::ProfileNode* node)
213 {
214     double startTime = node->calls()[0].startTime();
215     double endTime = node->calls().last().startTime() + node->calls().last().elapsedTime();
216
217     double totalTime = 0;
218     for (const JSC::ProfileNode::Call& call : node->calls())
219         totalTime += call.elapsedTime();
220
221     return Protocol::Timeline::CPUProfileNodeAggregateCallInfo::create()
222         .setCallCount(node->calls().size())
223         .setStartTime(startTime)
224         .setEndTime(endTime)
225         .setTotalTime(totalTime)
226         .release();
227 }
228
229 static Ref<Protocol::Timeline::CPUProfileNode> buildInspectorObject(const JSC::ProfileNode* node)
230 {
231     auto result = Protocol::Timeline::CPUProfileNode::create()
232         .setId(node->id())
233         .setCallInfo(buildAggregateCallInfoInspectorObject(node))
234         .release();
235
236     if (!node->functionName().isEmpty())
237         result->setFunctionName(node->functionName());
238
239     if (!node->url().isEmpty()) {
240         result->setUrl(node->url());
241         result->setLineNumber(node->lineNumber());
242         result->setColumnNumber(node->columnNumber());
243     }
244
245     if (!node->children().isEmpty()) {
246         auto children = Protocol::Array<Protocol::Timeline::CPUProfileNode>::create();
247         for (RefPtr<JSC::ProfileNode> profileNode : node->children())
248             children->addItem(buildInspectorObject(profileNode.get()));
249         result->setChildren(WTF::move(children));
250     }
251
252     return WTF::move(result);
253 }
254
255 static Ref<Protocol::Timeline::CPUProfile> buildProfileInspectorObject(const JSC::Profile* profile)
256 {
257     auto rootNodes = Protocol::Array<Protocol::Timeline::CPUProfileNode>::create();
258     for (RefPtr<JSC::ProfileNode> profileNode : profile->rootNode()->children())
259         rootNodes->addItem(buildInspectorObject(profileNode.get()));
260
261     return Protocol::Timeline::CPUProfile::create()
262         .setRootNodes(WTF::move(rootNodes))
263         .release();
264 }
265
266 void TimelineRecordFactory::appendProfile(InspectorObject* data, RefPtr<JSC::Profile>&& profile)
267 {
268     data->setValue(ASCIILiteral("profile"), buildProfileInspectorObject(profile.get()));
269 }
270
271 } // namespace WebCore