• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "config.h"
6 #include "core/inspector/InspectorTraceEvents.h"
7 
8 #include "bindings/core/v8/ScriptCallStackFactory.h"
9 #include "bindings/core/v8/ScriptGCEvent.h"
10 #include "bindings/core/v8/ScriptSourceCode.h"
11 #include "core/events/Event.h"
12 #include "core/frame/FrameView.h"
13 #include "core/frame/LocalFrame.h"
14 #include "core/inspector/IdentifiersFactory.h"
15 #include "core/inspector/InspectorNodeIds.h"
16 #include "core/inspector/ScriptCallStack.h"
17 #include "core/page/Page.h"
18 #include "core/rendering/RenderImage.h"
19 #include "core/rendering/RenderLayer.h"
20 #include "core/rendering/RenderObject.h"
21 #include "core/workers/WorkerThread.h"
22 #include "core/xml/XMLHttpRequest.h"
23 #include "platform/JSONValues.h"
24 #include "platform/TracedValue.h"
25 #include "platform/graphics/GraphicsLayer.h"
26 #include "platform/network/ResourceRequest.h"
27 #include "platform/network/ResourceResponse.h"
28 #include "platform/weborigin/KURL.h"
29 #include "wtf/Vector.h"
30 #include <inttypes.h>
31 
32 namespace blink {
33 
34 static const unsigned maxInvalidationTrackingCallstackSize = 5;
35 
36 namespace {
37 
38 class JSCallStack : public TraceEvent::ConvertableToTraceFormat  {
39 public:
JSCallStack(PassRefPtrWillBeRawPtr<ScriptCallStack> callstack)40     explicit JSCallStack(PassRefPtrWillBeRawPtr<ScriptCallStack> callstack)
41     {
42         m_serialized = callstack ? callstack->buildInspectorArray()->toJSONString() : "[]";
43         ASSERT(m_serialized.isSafeToSendToAnotherThread());
44     }
asTraceFormat() const45     virtual String asTraceFormat() const
46     {
47         return m_serialized;
48     }
49 
50 private:
51     String m_serialized;
52 };
53 
toHexString(const void * p)54 String toHexString(const void* p)
55 {
56     return String::format("0x%" PRIx64, static_cast<uint64>(reinterpret_cast<intptr_t>(p)));
57 }
58 
59 }
60 
beginData(FrameView * frameView)61 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorLayoutEvent::beginData(FrameView* frameView)
62 {
63     bool isPartial;
64     unsigned needsLayoutObjects;
65     unsigned totalObjects;
66     LocalFrame& frame = frameView->frame();
67     frame.countObjectsNeedingLayout(needsLayoutObjects, totalObjects, isPartial);
68 
69     RefPtr<TracedValue> value = TracedValue::create();
70     value->setInteger("dirtyObjects", needsLayoutObjects);
71     value->setInteger("totalObjects", totalObjects);
72     value->setBoolean("partialLayout", isPartial);
73     value->setString("frame", toHexString(&frame));
74     return value;
75 }
76 
createQuad(TracedValue * value,const char * name,const FloatQuad & quad)77 static void createQuad(TracedValue* value, const char* name, const FloatQuad& quad)
78 {
79     value->beginArray(name);
80     value->pushDouble(quad.p1().x());
81     value->pushDouble(quad.p1().y());
82     value->pushDouble(quad.p2().x());
83     value->pushDouble(quad.p2().y());
84     value->pushDouble(quad.p3().x());
85     value->pushDouble(quad.p3().y());
86     value->pushDouble(quad.p4().x());
87     value->pushDouble(quad.p4().y());
88     value->endArray();
89 }
90 
setGeneratingNodeInfo(TracedValue * value,const RenderObject * renderer,const char * idFieldName,const char * nameFieldName=0)91 static void setGeneratingNodeInfo(TracedValue* value, const RenderObject* renderer, const char* idFieldName, const char* nameFieldName = 0)
92 {
93     Node* node = 0;
94     for (; renderer && !node; renderer = renderer->parent())
95         node = renderer->generatingNode();
96     if (!node)
97         return;
98     value->setInteger(idFieldName, InspectorNodeIds::idForNode(node));
99     if (nameFieldName)
100         value->setString(nameFieldName, node->debugName());
101 }
102 
endData(RenderObject * rootForThisLayout)103 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorLayoutEvent::endData(RenderObject* rootForThisLayout)
104 {
105     Vector<FloatQuad> quads;
106     rootForThisLayout->absoluteQuads(quads);
107 
108     RefPtr<TracedValue> value = TracedValue::create();
109     if (quads.size() >= 1) {
110         createQuad(value.get(), "root", quads[0]);
111         setGeneratingNodeInfo(value.get(), rootForThisLayout, "rootNode");
112     } else {
113         ASSERT_NOT_REACHED();
114     }
115     return value;
116 }
117 
data(const RenderObject * renderer)118 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorLayoutInvalidationTrackingEvent::data(const RenderObject* renderer)
119 {
120     ASSERT(renderer);
121     RefPtr<TracedValue> value = TracedValue::create();
122     value->setString("frame", toHexString(renderer->frame()));
123     setGeneratingNodeInfo(value.get(), renderer, "nodeId", "nodeName");
124     RefPtrWillBeRawPtr<ScriptCallStack> callstack = createScriptCallStack(maxInvalidationTrackingCallstackSize, true);
125     value->setString("callstack", callstack ? callstack->buildInspectorArray()->toJSONString() : "[]");
126     return value;
127 }
128 
data(const RenderObject * renderer,const RenderObject * paintContainer)129 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorPaintInvalidationTrackingEvent::data(const RenderObject* renderer, const RenderObject* paintContainer)
130 {
131     ASSERT(renderer);
132     RefPtr<TracedValue> value = TracedValue::create();
133     value->setString("frame", toHexString(renderer->frame()));
134     setGeneratingNodeInfo(value.get(), paintContainer, "paintId");
135     setGeneratingNodeInfo(value.get(), renderer, "nodeId", "nodeName");
136     return value;
137 }
138 
data(unsigned long identifier,LocalFrame * frame,const ResourceRequest & request)139 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorSendRequestEvent::data(unsigned long identifier, LocalFrame* frame, const ResourceRequest& request)
140 {
141     String requestId = IdentifiersFactory::requestId(identifier);
142 
143     RefPtr<TracedValue> value = TracedValue::create();
144     value->setString("requestId", requestId);
145     value->setString("frame", toHexString(frame));
146     value->setString("url", request.url().string());
147     value->setString("requestMethod", request.httpMethod());
148     return value;
149 }
150 
data(unsigned long identifier,LocalFrame * frame,const ResourceResponse & response)151 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorReceiveResponseEvent::data(unsigned long identifier, LocalFrame* frame, const ResourceResponse& response)
152 {
153     String requestId = IdentifiersFactory::requestId(identifier);
154 
155     RefPtr<TracedValue> value = TracedValue::create();
156     value->setString("requestId", requestId);
157     value->setString("frame", toHexString(frame));
158     value->setInteger("statusCode", response.httpStatusCode());
159     value->setString("mimeType", response.mimeType().string().isolatedCopy());
160     return value;
161 }
162 
data(unsigned long identifier,LocalFrame * frame,int encodedDataLength)163 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorReceiveDataEvent::data(unsigned long identifier, LocalFrame* frame, int encodedDataLength)
164 {
165     String requestId = IdentifiersFactory::requestId(identifier);
166 
167     RefPtr<TracedValue> value = TracedValue::create();
168     value->setString("requestId", requestId);
169     value->setString("frame", toHexString(frame));
170     value->setInteger("encodedDataLength", encodedDataLength);
171     return value;
172 }
173 
data(unsigned long identifier,double finishTime,bool didFail)174 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorResourceFinishEvent::data(unsigned long identifier, double finishTime, bool didFail)
175 {
176     String requestId = IdentifiersFactory::requestId(identifier);
177 
178     RefPtr<TracedValue> value = TracedValue::create();
179     value->setString("requestId", requestId);
180     value->setBoolean("didFail", didFail);
181     if (finishTime)
182         value->setDouble("networkTime", finishTime);
183     return value;
184 }
185 
frameForExecutionContext(ExecutionContext * context)186 static LocalFrame* frameForExecutionContext(ExecutionContext* context)
187 {
188     LocalFrame* frame = 0;
189     if (context->isDocument())
190         frame = toDocument(context)->frame();
191     return frame;
192 }
193 
genericTimerData(ExecutionContext * context,int timerId)194 static PassRefPtr<TracedValue> genericTimerData(ExecutionContext* context, int timerId)
195 {
196     RefPtr<TracedValue> value = TracedValue::create();
197     value->setInteger("timerId", timerId);
198     if (LocalFrame* frame = frameForExecutionContext(context))
199         value->setString("frame", toHexString(frame));
200     return value.release();
201 }
202 
data(ExecutionContext * context,int timerId,int timeout,bool singleShot)203 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerInstallEvent::data(ExecutionContext* context, int timerId, int timeout, bool singleShot)
204 {
205     RefPtr<TracedValue> value = genericTimerData(context, timerId);
206     value->setInteger("timeout", timeout);
207     value->setBoolean("singleShot", singleShot);
208     return value;
209 }
210 
data(ExecutionContext * context,int timerId)211 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerRemoveEvent::data(ExecutionContext* context, int timerId)
212 {
213     return genericTimerData(context, timerId);
214 }
215 
data(ExecutionContext * context,int timerId)216 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerFireEvent::data(ExecutionContext* context, int timerId)
217 {
218     return genericTimerData(context, timerId);
219 }
220 
data(Document * document,int callbackId)221 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorAnimationFrameEvent::data(Document* document, int callbackId)
222 {
223     RefPtr<TracedValue> value = TracedValue::create();
224     value->setInteger("id", callbackId);
225     value->setString("frame", toHexString(document->frame()));
226     return value;
227 }
228 
data(Document * document,unsigned long identifier,const KURL & url,const String & protocol)229 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorWebSocketCreateEvent::data(Document* document, unsigned long identifier, const KURL& url, const String& protocol)
230 {
231     RefPtr<TracedValue> value = TracedValue::create();
232     value->setInteger("identifier", identifier);
233     value->setString("url", url.string());
234     value->setString("frame", toHexString(document->frame()));
235     if (!protocol.isNull())
236         value->setString("webSocketProtocol", protocol);
237     return value;
238 }
239 
data(Document * document,unsigned long identifier)240 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorWebSocketEvent::data(Document* document, unsigned long identifier)
241 {
242     RefPtr<TracedValue> value = TracedValue::create();
243     value->setInteger("identifier", identifier);
244     value->setString("frame", toHexString(document->frame()));
245     return value;
246 }
247 
beginData(Document * document,unsigned startLine)248 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorParseHtmlEvent::beginData(Document* document, unsigned startLine)
249 {
250     RefPtr<TracedValue> value = TracedValue::create();
251     value->setInteger("startLine", startLine);
252     value->setString("frame", toHexString(document->frame()));
253     return value;
254 }
255 
data(ExecutionContext * context,XMLHttpRequest * request)256 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorXhrReadyStateChangeEvent::data(ExecutionContext* context, XMLHttpRequest* request)
257 {
258     RefPtr<TracedValue> value = TracedValue::create();
259     value->setString("url", request->url().string());
260     value->setInteger("readyState", request->readyState());
261     if (LocalFrame* frame = frameForExecutionContext(context))
262         value->setString("frame", toHexString(frame));
263     return value;
264 }
265 
data(ExecutionContext * context,XMLHttpRequest * request)266 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorXhrLoadEvent::data(ExecutionContext* context, XMLHttpRequest* request)
267 {
268     RefPtr<TracedValue> value = TracedValue::create();
269     value->setString("url", request->url().string());
270     if (LocalFrame* frame = frameForExecutionContext(context))
271         value->setString("frame", toHexString(frame));
272     return value;
273 }
274 
localToPageQuad(const RenderObject & renderer,const LayoutRect & rect,FloatQuad * quad)275 static void localToPageQuad(const RenderObject& renderer, const LayoutRect& rect, FloatQuad* quad)
276 {
277     LocalFrame* frame = renderer.frame();
278     FrameView* view = frame->view();
279     FloatQuad absolute = renderer.localToAbsoluteQuad(FloatQuad(rect));
280     quad->setP1(view->contentsToRootView(roundedIntPoint(absolute.p1())));
281     quad->setP2(view->contentsToRootView(roundedIntPoint(absolute.p2())));
282     quad->setP3(view->contentsToRootView(roundedIntPoint(absolute.p3())));
283     quad->setP4(view->contentsToRootView(roundedIntPoint(absolute.p4())));
284 }
285 
286 const char InspectorLayerInvalidationTrackingEvent::SquashingLayerGeometryWasUpdated[] = "Squashing layer geometry was updated.";
287 const char InspectorLayerInvalidationTrackingEvent::AddedToSquashingLayer[] = "The layer may have been added to an already-existing squashing layer.";
288 const char InspectorLayerInvalidationTrackingEvent::RemovedFromSquashingLayer[] = "Removed the layer from a squashing layer.";
289 const char InspectorLayerInvalidationTrackingEvent::ReflectionLayerChanged[] = "Reflection layer change.";
290 const char InspectorLayerInvalidationTrackingEvent::NewCompositedLayer[] = "Assigned a new composited layer.";
291 const char InspectorLayerInvalidationTrackingEvent::AncestorRequiresNewLayer[] = "A new composited layer is needed based on the RenderLayer's compositing ancestor's properties.";
292 
data(const RenderLayer * layer,const char * reason)293 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorLayerInvalidationTrackingEvent::data(const RenderLayer* layer, const char* reason)
294 {
295     const RenderObject* paintInvalidationContainer = layer->renderer()->containerForPaintInvalidation();
296 
297     RefPtr<TracedValue> value = TracedValue::create();
298     value->setString("frame", toHexString(paintInvalidationContainer->frame()));
299     setGeneratingNodeInfo(value.get(), paintInvalidationContainer, "paintId");
300     value->setString("reason", reason);
301     return value;
302 }
303 
data(RenderObject * renderer,const LayoutRect & clipRect,const GraphicsLayer * graphicsLayer)304 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorPaintEvent::data(RenderObject* renderer, const LayoutRect& clipRect, const GraphicsLayer* graphicsLayer)
305 {
306     RefPtr<TracedValue> value = TracedValue::create();
307     value->setString("frame", toHexString(renderer->frame()));
308     FloatQuad quad;
309     localToPageQuad(*renderer, clipRect, &quad);
310     createQuad(value.get(), "clip", quad);
311     setGeneratingNodeInfo(value.get(), renderer, "nodeId");
312     int graphicsLayerId = graphicsLayer ? graphicsLayer->platformLayer()->id() : 0;
313     value->setInteger("layerId", graphicsLayerId);
314     return value;
315 }
316 
data(LocalFrame * frame)317 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorMarkLoadEvent::data(LocalFrame* frame)
318 {
319     RefPtr<TracedValue> value = TracedValue::create();
320     value->setString("frame", toHexString(frame));
321     bool isMainFrame = frame && frame->isMainFrame();
322     value->setBoolean("isMainFrame", isMainFrame);
323     return value;
324 }
325 
data(RenderObject * renderer)326 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorScrollLayerEvent::data(RenderObject* renderer)
327 {
328     RefPtr<TracedValue> value = TracedValue::create();
329     value->setString("frame", toHexString(renderer->frame()));
330     setGeneratingNodeInfo(value.get(), renderer, "nodeId");
331     return value;
332 }
333 
data(LocalFrame * frame,const String & url,int lineNumber)334 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorEvaluateScriptEvent::data(LocalFrame* frame, const String& url, int lineNumber)
335 {
336     RefPtr<TracedValue> value = TracedValue::create();
337     value->setString("frame", toHexString(frame));
338     value->setString("url", url);
339     value->setInteger("lineNumber", lineNumber);
340     return value;
341 }
342 
data(ExecutionContext * context,int scriptId,const String & scriptName,int scriptLine)343 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorFunctionCallEvent::data(ExecutionContext* context, int scriptId, const String& scriptName, int scriptLine)
344 {
345     RefPtr<TracedValue> value = TracedValue::create();
346     value->setString("scriptId", String::number(scriptId));
347     value->setString("scriptName", scriptName);
348     value->setInteger("scriptLine", scriptLine);
349     if (LocalFrame* frame = frameForExecutionContext(context))
350         value->setString("frame", toHexString(frame));
351     return value;
352 }
353 
data(const RenderImage & renderImage)354 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorPaintImageEvent::data(const RenderImage& renderImage)
355 {
356     RefPtr<TracedValue> value = TracedValue::create();
357     setGeneratingNodeInfo(value.get(), &renderImage, "nodeId");
358     if (const ImageResource* resource = renderImage.cachedImage())
359         value->setString("url", resource->url().string());
360     return value;
361 }
362 
usedHeapSize()363 static size_t usedHeapSize()
364 {
365     HeapInfo info;
366     ScriptGCEvent::getHeapSize(info);
367     return info.usedJSHeapSize;
368 }
369 
data()370 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorUpdateCountersEvent::data()
371 {
372     RefPtr<TracedValue> value = TracedValue::create();
373     if (isMainThread()) {
374         value->setInteger("documents", InspectorCounters::counterValue(InspectorCounters::DocumentCounter));
375         value->setInteger("nodes", InspectorCounters::counterValue(InspectorCounters::NodeCounter));
376         value->setInteger("jsEventListeners", InspectorCounters::counterValue(InspectorCounters::JSEventListenerCounter));
377     }
378     value->setDouble("jsHeapSizeUsed", static_cast<double>(usedHeapSize()));
379     return value;
380 }
381 
currentCallStack()382 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorCallStackEvent::currentCallStack()
383 {
384     return adoptRef(new JSCallStack(createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true)));
385 }
386 
data(const Event & event)387 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorEventDispatchEvent::data(const Event& event)
388 {
389     RefPtr<TracedValue> value = TracedValue::create();
390     value->setString("type", event.type());
391     return value;
392 }
393 
data(ExecutionContext * context,const String & message)394 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimeStampEvent::data(ExecutionContext* context, const String& message)
395 {
396     RefPtr<TracedValue> value = TracedValue::create();
397     value->setString("message", message);
398     if (LocalFrame* frame = frameForExecutionContext(context))
399         value->setString("frame", toHexString(frame));
400     return value;
401 }
402 
data(const String & sessionId,WorkerThread * workerThread)403 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTracingSessionIdForWorkerEvent::data(const String& sessionId, WorkerThread* workerThread)
404 {
405     RefPtr<TracedValue> value = TracedValue::create();
406     value->setString("sessionId", sessionId);
407     value->setDouble("workerThreadId", workerThread->platformThreadId());
408     return value;
409 }
410 
411 }
412