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