Home | History | Annotate | Download | only in inspector
      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:
     40     explicit JSCallStack(PassRefPtrWillBeRawPtr<ScriptCallStack> callstack)
     41     {
     42         m_serialized = callstack ? callstack->buildInspectorArray()->toJSONString() : "[]";
     43         ASSERT(m_serialized.isSafeToSendToAnotherThread());
     44     }
     45     virtual String asTraceFormat() const
     46     {
     47         return m_serialized;
     48     }
     49 
     50 private:
     51     String m_serialized;
     52 };
     53 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    211 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerRemoveEvent::data(ExecutionContext* context, int timerId)
    212 {
    213     return genericTimerData(context, timerId);
    214 }
    215 
    216 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerFireEvent::data(ExecutionContext* context, int timerId)
    217 {
    218     return genericTimerData(context, timerId);
    219 }
    220 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    363 static size_t usedHeapSize()
    364 {
    365     HeapInfo info;
    366     ScriptGCEvent::getHeapSize(info);
    367     return info.usedJSHeapSize;
    368 }
    369 
    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 
    382 PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorCallStackEvent::currentCallStack()
    383 {
    384     return adoptRef(new JSCallStack(createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true)));
    385 }
    386 
    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 
    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 
    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