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 32namespace blink { 33 34static const unsigned maxInvalidationTrackingCallstackSize = 5; 35 36namespace { 37 38class JSCallStack : public TraceEvent::ConvertableToTraceFormat { 39public: 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 50private: 51 String m_serialized; 52}; 53 54String toHexString(const void* p) 55{ 56 return String::format("0x%" PRIx64, static_cast<uint64>(reinterpret_cast<intptr_t>(p))); 57} 58 59} 60 61PassRefPtr<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 77static 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 91static 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 103PassRefPtr<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 118PassRefPtr<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 129PassRefPtr<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 139PassRefPtr<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 151PassRefPtr<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 163PassRefPtr<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 174PassRefPtr<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 186static LocalFrame* frameForExecutionContext(ExecutionContext* context) 187{ 188 LocalFrame* frame = 0; 189 if (context->isDocument()) 190 frame = toDocument(context)->frame(); 191 return frame; 192} 193 194static 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 203PassRefPtr<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 211PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerRemoveEvent::data(ExecutionContext* context, int timerId) 212{ 213 return genericTimerData(context, timerId); 214} 215 216PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerFireEvent::data(ExecutionContext* context, int timerId) 217{ 218 return genericTimerData(context, timerId); 219} 220 221PassRefPtr<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 229PassRefPtr<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 240PassRefPtr<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 248PassRefPtr<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 256PassRefPtr<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 266PassRefPtr<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 275static 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 286const char InspectorLayerInvalidationTrackingEvent::SquashingLayerGeometryWasUpdated[] = "Squashing layer geometry was updated."; 287const char InspectorLayerInvalidationTrackingEvent::AddedToSquashingLayer[] = "The layer may have been added to an already-existing squashing layer."; 288const char InspectorLayerInvalidationTrackingEvent::RemovedFromSquashingLayer[] = "Removed the layer from a squashing layer."; 289const char InspectorLayerInvalidationTrackingEvent::ReflectionLayerChanged[] = "Reflection layer change."; 290const char InspectorLayerInvalidationTrackingEvent::NewCompositedLayer[] = "Assigned a new composited layer."; 291const char InspectorLayerInvalidationTrackingEvent::AncestorRequiresNewLayer[] = "A new composited layer is needed based on the RenderLayer's compositing ancestor's properties."; 292 293PassRefPtr<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 304PassRefPtr<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 317PassRefPtr<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 326PassRefPtr<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 334PassRefPtr<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 343PassRefPtr<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 354PassRefPtr<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 363static size_t usedHeapSize() 364{ 365 HeapInfo info; 366 ScriptGCEvent::getHeapSize(info); 367 return info.usedJSHeapSize; 368} 369 370PassRefPtr<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 382PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorCallStackEvent::currentCallStack() 383{ 384 return adoptRef(new JSCallStack(createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true))); 385} 386 387PassRefPtr<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 394PassRefPtr<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 403PassRefPtr<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