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/v8/ScriptCallStackFactory.h" 9#include "bindings/v8/ScriptGCEvent.h" 10#include "bindings/v8/ScriptSourceCode.h" 11#include "core/frame/FrameView.h" 12#include "core/frame/LocalFrame.h" 13#include "core/inspector/IdentifiersFactory.h" 14#include "core/inspector/InspectorNodeIds.h" 15#include "core/inspector/ScriptCallStack.h" 16#include "core/page/Page.h" 17#include "core/rendering/RenderImage.h" 18#include "core/rendering/RenderObject.h" 19#include "core/xml/XMLHttpRequest.h" 20#include "platform/JSONValues.h" 21#include "platform/TracedValue.h" 22#include "platform/graphics/GraphicsLayer.h" 23#include "platform/network/ResourceRequest.h" 24#include "platform/network/ResourceResponse.h" 25#include "platform/weborigin/KURL.h" 26#include "wtf/Vector.h" 27#include <inttypes.h> 28 29namespace WebCore { 30 31namespace { 32 33class JSCallStack : public TraceEvent::ConvertableToTraceFormat { 34public: 35 explicit JSCallStack(PassRefPtrWillBeRawPtr<ScriptCallStack> callstack) : m_callstack(callstack) { } 36 virtual String asTraceFormat() const 37 { 38 if (!m_callstack) 39 return "null"; 40 return m_callstack->buildInspectorArray()->toJSONString(); 41 } 42 43private: 44 RefPtrWillBePersistent<ScriptCallStack> m_callstack; 45}; 46 47String toHexString(void* p) 48{ 49 return String::format("0x%" PRIx64, static_cast<uint64>(reinterpret_cast<intptr_t>(p))); 50} 51 52} 53 54PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorLayoutEvent::beginData(FrameView* frameView) 55{ 56 bool isPartial; 57 unsigned needsLayoutObjects; 58 unsigned totalObjects; 59 LocalFrame& frame = frameView->frame(); 60 frame.countObjectsNeedingLayout(needsLayoutObjects, totalObjects, isPartial); 61 62 RefPtr<JSONObject> data = JSONObject::create(); 63 data->setNumber("dirtyObjects", needsLayoutObjects); 64 data->setNumber("totalObjects", totalObjects); 65 data->setBoolean("partialLayout", isPartial); 66 data->setString("frame", toHexString(&frame)); 67 return TracedValue::fromJSONValue(data); 68} 69 70static PassRefPtr<JSONArray> createQuad(const FloatQuad& quad) 71{ 72 RefPtr<JSONArray> array = JSONArray::create(); 73 array->pushNumber(quad.p1().x()); 74 array->pushNumber(quad.p1().y()); 75 array->pushNumber(quad.p2().x()); 76 array->pushNumber(quad.p2().y()); 77 array->pushNumber(quad.p3().x()); 78 array->pushNumber(quad.p3().y()); 79 array->pushNumber(quad.p4().x()); 80 array->pushNumber(quad.p4().y()); 81 return array.release(); 82} 83 84PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorLayoutEvent::endData(RenderObject* rootForThisLayout) 85{ 86 Vector<FloatQuad> quads; 87 rootForThisLayout->absoluteQuads(quads); 88 89 RefPtr<JSONObject> data = JSONObject::create(); 90 if (quads.size() >= 1) { 91 data->setArray("root", createQuad(quads[0])); 92 int rootNodeId = InspectorNodeIds::idForNode(rootForThisLayout->generatingNode()); 93 data->setNumber("rootNode", rootNodeId); 94 } else { 95 ASSERT_NOT_REACHED(); 96 } 97 return TracedValue::fromJSONValue(data); 98} 99 100PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorSendRequestEvent::data(unsigned long identifier, LocalFrame* frame, const ResourceRequest& request) 101{ 102 String requestId = IdentifiersFactory::requestId(identifier); 103 104 RefPtr<JSONObject> data = JSONObject::create(); 105 data->setString("requestId", requestId); 106 data->setString("frame", toHexString(frame)); 107 data->setString("url", request.url().string()); 108 data->setString("requestMethod", request.httpMethod()); 109 return TracedValue::fromJSONValue(data); 110} 111 112PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorReceiveResponseEvent::data(unsigned long identifier, LocalFrame* frame, const ResourceResponse& response) 113{ 114 String requestId = IdentifiersFactory::requestId(identifier); 115 116 RefPtr<JSONObject> data = JSONObject::create(); 117 data->setString("requestId", requestId); 118 data->setString("frame", toHexString(frame)); 119 data->setNumber("statusCode", response.httpStatusCode()); 120 data->setString("mimeType", response.mimeType().string().isolatedCopy()); 121 return TracedValue::fromJSONValue(data); 122} 123 124PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorReceiveDataEvent::data(unsigned long identifier, LocalFrame* frame, int encodedDataLength) 125{ 126 String requestId = IdentifiersFactory::requestId(identifier); 127 128 RefPtr<JSONObject> data = JSONObject::create(); 129 data->setString("requestId", requestId); 130 data->setString("frame", toHexString(frame)); 131 data->setNumber("encodedDataLength", encodedDataLength); 132 return TracedValue::fromJSONValue(data); 133} 134 135PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorResourceFinishEvent::data(unsigned long identifier, double finishTime, bool didFail) 136{ 137 String requestId = IdentifiersFactory::requestId(identifier); 138 139 RefPtr<JSONObject> data = JSONObject::create(); 140 data->setString("requestId", requestId); 141 data->setBoolean("didFail", didFail); 142 if (finishTime) 143 data->setNumber("networkTime", finishTime); 144 return TracedValue::fromJSONValue(data); 145} 146 147static LocalFrame* frameForExecutionContext(ExecutionContext* context) 148{ 149 LocalFrame* frame = 0; 150 if (context->isDocument()) 151 frame = toDocument(context)->frame(); 152 return frame; 153} 154 155static PassRefPtr<JSONObject> genericTimerData(ExecutionContext* context, int timerId) 156{ 157 RefPtr<JSONObject> data = JSONObject::create(); 158 data->setNumber("timerId", timerId); 159 if (LocalFrame* frame = frameForExecutionContext(context)) 160 data->setString("frame", toHexString(frame)); 161 return data.release(); 162} 163 164PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerInstallEvent::data(ExecutionContext* context, int timerId, int timeout, bool singleShot) 165{ 166 RefPtr<JSONObject> data = genericTimerData(context, timerId); 167 data->setNumber("timeout", timeout); 168 data->setBoolean("singleShot", singleShot); 169 return TracedValue::fromJSONValue(data); 170} 171 172PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerRemoveEvent::data(ExecutionContext* context, int timerId) 173{ 174 return TracedValue::fromJSONValue(genericTimerData(context, timerId)); 175} 176 177PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorTimerFireEvent::data(ExecutionContext* context, int timerId) 178{ 179 return TracedValue::fromJSONValue(genericTimerData(context, timerId)); 180} 181 182PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorAnimationFrameEvent::data(Document* document, int callbackId) 183{ 184 RefPtr<JSONObject> data = JSONObject::create(); 185 data->setNumber("id", callbackId); 186 data->setString("frame", toHexString(document->frame())); 187 return TracedValue::fromJSONValue(data); 188} 189 190PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorWebSocketCreateEvent::data(Document* document, unsigned long identifier, const KURL& url, const String& protocol) 191{ 192 RefPtr<JSONObject> data = JSONObject::create(); 193 data->setNumber("identifier", identifier); 194 data->setString("url", url.string()); 195 data->setString("frame", toHexString(document->frame())); 196 if (!protocol.isNull()) 197 data->setString("webSocketProtocol", protocol); 198 return TracedValue::fromJSONValue(data); 199} 200 201PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorWebSocketEvent::data(Document* document, unsigned long identifier) 202{ 203 RefPtr<JSONObject> data = JSONObject::create(); 204 data->setNumber("identifier", identifier); 205 data->setString("frame", toHexString(document->frame())); 206 return TracedValue::fromJSONValue(data); 207} 208 209PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorParseHtmlEvent::beginData(Document* document, unsigned startLine) 210{ 211 RefPtr<JSONObject> data = JSONObject::create(); 212 data->setNumber("startLine", startLine); 213 data->setString("frame", toHexString(document->frame())); 214 return TracedValue::fromJSONValue(data); 215} 216 217PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorXhrReadyStateChangeEvent::data(ExecutionContext* context, XMLHttpRequest* request) 218{ 219 RefPtr<JSONObject> data = JSONObject::create(); 220 data->setString("url", request->url().string()); 221 data->setNumber("readyState", request->readyState()); 222 if (LocalFrame* frame = frameForExecutionContext(context)) 223 data->setString("frame", toHexString(frame)); 224 return TracedValue::fromJSONValue(data); 225} 226 227PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorXhrLoadEvent::data(ExecutionContext* context, XMLHttpRequest* request) 228{ 229 RefPtr<JSONObject> data = JSONObject::create(); 230 data->setString("url", request->url().string()); 231 if (LocalFrame* frame = frameForExecutionContext(context)) 232 data->setString("frame", toHexString(frame)); 233 return TracedValue::fromJSONValue(data); 234} 235 236static void localToPageQuad(const RenderObject& renderer, const LayoutRect& rect, FloatQuad* quad) 237{ 238 LocalFrame* frame = renderer.frame(); 239 FrameView* view = frame->view(); 240 FloatQuad absolute = renderer.localToAbsoluteQuad(FloatQuad(rect)); 241 quad->setP1(view->contentsToRootView(roundedIntPoint(absolute.p1()))); 242 quad->setP2(view->contentsToRootView(roundedIntPoint(absolute.p2()))); 243 quad->setP3(view->contentsToRootView(roundedIntPoint(absolute.p3()))); 244 quad->setP4(view->contentsToRootView(roundedIntPoint(absolute.p4()))); 245} 246 247PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorPaintEvent::data(RenderObject* renderer, const LayoutRect& clipRect, const GraphicsLayer* graphicsLayer) 248{ 249 RefPtr<JSONObject> data = JSONObject::create(); 250 data->setString("frame", toHexString(renderer->frame())); 251 FloatQuad quad; 252 localToPageQuad(*renderer, clipRect, &quad); 253 data->setArray("clip", createQuad(quad)); 254 int nodeId = InspectorNodeIds::idForNode(renderer->generatingNode()); 255 data->setNumber("nodeId", nodeId); 256 int graphicsLayerId = graphicsLayer ? graphicsLayer->platformLayer()->id() : 0; 257 data->setNumber("layerId", graphicsLayerId); 258 return TracedValue::fromJSONValue(data); 259} 260 261PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorMarkLoadEvent::data(LocalFrame* frame) 262{ 263 RefPtr<JSONObject> data = JSONObject::create(); 264 data->setString("frame", toHexString(frame)); 265 bool isMainFrame = frame && frame->page()->mainFrame() == frame; 266 data->setBoolean("isMainFrame", isMainFrame); 267 return TracedValue::fromJSONValue(data); 268} 269 270PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorScrollLayerEvent::data(RenderObject* renderer) 271{ 272 RefPtr<JSONObject> data = JSONObject::create(); 273 data->setString("frame", toHexString(renderer->frame())); 274 int nodeId = InspectorNodeIds::idForNode(renderer->generatingNode()); 275 data->setNumber("nodeId", nodeId); 276 return TracedValue::fromJSONValue(data); 277} 278 279PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorEvaluateScriptEvent::data(LocalFrame* frame, const String& url, int lineNumber) 280{ 281 RefPtr<JSONObject> data = JSONObject::create(); 282 data->setString("frame", toHexString(frame)); 283 data->setString("url", url); 284 data->setNumber("lineNumber", lineNumber); 285 return TracedValue::fromJSONValue(data); 286} 287 288PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorFunctionCallEvent::data(ExecutionContext* context, int scriptId, const String& scriptName, int scriptLine) 289{ 290 RefPtr<JSONObject> data = JSONObject::create(); 291 data->setString("scriptId", String::number(scriptId)); 292 data->setString("scriptName", scriptName); 293 data->setNumber("scriptLine", scriptLine); 294 if (LocalFrame* frame = frameForExecutionContext(context)) 295 data->setString("frame", toHexString(frame)); 296 return TracedValue::fromJSONValue(data); 297} 298 299PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorPaintImageEvent::data(const RenderImage& renderImage) 300{ 301 RefPtr<JSONObject> data = JSONObject::create(); 302 data->setNumber("nodeId", InspectorNodeIds::idForNode(renderImage.generatingNode())); 303 304 if (const ImageResource* resource = renderImage.cachedImage()) 305 data->setString("url", resource->url().string()); 306 307 return TracedValue::fromJSONValue(data); 308} 309 310static size_t usedHeapSize() 311{ 312 HeapInfo info; 313 ScriptGCEvent::getHeapSize(info); 314 return info.usedJSHeapSize; 315} 316 317PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorUpdateCountersEvent::data() 318{ 319 RefPtr<JSONObject> data = JSONObject::create(); 320 if (isMainThread()) { 321 data->setNumber("documents", InspectorCounters::counterValue(InspectorCounters::DocumentCounter)); 322 data->setNumber("nodes", InspectorCounters::counterValue(InspectorCounters::NodeCounter)); 323 data->setNumber("jsEventListeners", InspectorCounters::counterValue(InspectorCounters::JSEventListenerCounter)); 324 } 325 data->setNumber("jsHeapSizeUsed", static_cast<double>(usedHeapSize())); 326 return TracedValue::fromJSONValue(data); 327} 328 329PassRefPtr<TraceEvent::ConvertableToTraceFormat> InspectorCallStackEvent::currentCallStack() 330{ 331 return adoptRef(new JSCallStack(createScriptCallStack(ScriptCallStack::maxCallStackSizeToCapture, true))); 332} 333 334} 335