1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #ifndef InspectorTimelineAgent_h 32 #define InspectorTimelineAgent_h 33 34 35 #include "InspectorFrontend.h" 36 #include "bindings/v8/ScriptGCEvent.h" 37 #include "core/events/EventPath.h" 38 #include "core/inspector/InspectorBaseAgent.h" 39 #include "core/inspector/ScriptGCEventListener.h" 40 #include "core/inspector/TraceEventDispatcher.h" 41 #include "platform/JSONValues.h" 42 #include "platform/PlatformInstrumentation.h" 43 #include "platform/geometry/LayoutRect.h" 44 #include "wtf/PassOwnPtr.h" 45 #include "wtf/Vector.h" 46 #include "wtf/WeakPtr.h" 47 48 namespace WebCore { 49 struct FetchInitiatorInfo; 50 struct TimelineGCEvent; 51 struct TimelineImageInfo; 52 struct TimelineThreadState; 53 struct TimelineRecordEntry; 54 55 class DOMWindow; 56 class Document; 57 class DocumentLoader; 58 class Event; 59 class FloatQuad; 60 class Frame; 61 class GraphicsContext; 62 class GraphicsLayer; 63 class InspectorClient; 64 class InspectorDOMAgent; 65 class InspectorFrontend; 66 class InspectorMemoryAgent; 67 class InspectorOverlay; 68 class InspectorPageAgent; 69 class InstrumentingAgents; 70 class KURL; 71 class Node; 72 class Page; 73 class RenderImage; 74 class RenderObject; 75 class ResourceError; 76 class ResourceLoader; 77 class ResourceRequest; 78 class ResourceResponse; 79 class ScriptArguments; 80 class ScriptCallStack; 81 class TimelineRecordStack; 82 class ExecutionContext; 83 class ScriptState; 84 class WebSocketHandshakeRequest; 85 class WebSocketHandshakeResponse; 86 class XMLHttpRequest; 87 88 typedef String ErrorString; 89 90 namespace TimelineRecordType { 91 extern const char ActivateLayerTree[]; 92 extern const char BeginFrame[]; 93 extern const char DecodeImage[]; 94 extern const char GPUTask[]; 95 extern const char PaintSetup[]; 96 extern const char Rasterize[]; 97 }; 98 99 class TimelineTimeConverter { 100 public: 101 TimelineTimeConverter() 102 : m_startOffset(0) 103 { 104 } 105 double fromMonotonicallyIncreasingTime(double time) const { return (time - m_startOffset) * 1000.0; } 106 void reset(); 107 108 private: 109 double m_startOffset; 110 }; 111 112 class InspectorTimelineAgent 113 : public TraceEventTarget<InspectorTimelineAgent> 114 , public InspectorBaseAgent<InspectorTimelineAgent> 115 , public ScriptGCEventListener 116 , public InspectorBackendDispatcher::TimelineCommandHandler 117 , public PlatformInstrumentationClient { 118 WTF_MAKE_NONCOPYABLE(InspectorTimelineAgent); 119 public: 120 enum InspectorType { PageInspector, WorkerInspector }; 121 122 class GPUEvent { 123 public: 124 enum Phase { PhaseBegin, PhaseEnd }; 125 GPUEvent(double timestamp, int phase, bool foreign, size_t usedGPUMemoryBytes) : 126 timestamp(timestamp), 127 phase(static_cast<Phase>(phase)), 128 foreign(foreign), 129 usedGPUMemoryBytes(usedGPUMemoryBytes) { } 130 double timestamp; 131 Phase phase; 132 bool foreign; 133 size_t usedGPUMemoryBytes; 134 }; 135 136 static PassOwnPtr<InspectorTimelineAgent> create(InstrumentingAgents* instrumentingAgents, InspectorPageAgent* pageAgent, InspectorMemoryAgent* memoryAgent, InspectorDOMAgent* domAgent, InspectorOverlay* overlay, InspectorCompositeState* state, InspectorType type, InspectorClient* client) 137 { 138 return adoptPtr(new InspectorTimelineAgent(instrumentingAgents, pageAgent, memoryAgent, domAgent, overlay, state, type, client)); 139 } 140 141 ~InspectorTimelineAgent(); 142 143 virtual void setFrontend(InspectorFrontend*); 144 virtual void clearFrontend(); 145 virtual void restore(); 146 147 virtual void enable(ErrorString*); 148 virtual void disable(ErrorString*); 149 virtual void start(ErrorString*, const int* maxCallStackDepth, const bool* bufferEvents, const bool* includeDomCounters, const bool* includeGPUEvents); 150 virtual void stop(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::Timeline::TimelineEvent> >& events); 151 152 void setLayerTreeId(int layerTreeId) { m_layerTreeId = layerTreeId; } 153 int id() const { return m_id; } 154 155 void didCommitLoad(); 156 157 // Methods called from WebCore. 158 bool willCallFunction(ExecutionContext*, const String& scriptName, int scriptLine); 159 void didCallFunction(); 160 161 bool willDispatchEvent(Document* document, const Event& event, DOMWindow* window, Node* node, const EventPath& eventPath); 162 bool willDispatchEventOnWindow(const Event& event, DOMWindow* window); 163 void didDispatchEvent(); 164 void didDispatchEventOnWindow(); 165 166 void didBeginFrame(int frameId); 167 void didCancelFrame(); 168 169 void didInvalidateLayout(Frame*); 170 bool willLayout(Frame*); 171 void didLayout(RenderObject*); 172 173 void willAutosizeText(RenderObject*); 174 void didAutosizeText(RenderObject*); 175 176 void didScheduleStyleRecalculation(Document*); 177 bool willRecalculateStyle(Document*); 178 void didRecalculateStyle(); 179 void didRecalculateStyleForElement(); 180 181 void willPaint(RenderObject*, const GraphicsLayer*); 182 void didPaint(RenderObject*, const GraphicsLayer*, GraphicsContext*, const LayoutRect&); 183 184 void willPaintImage(RenderImage*); 185 void didPaintImage(); 186 187 void willScrollLayer(RenderObject*); 188 void didScrollLayer(); 189 190 void willComposite(); 191 void didComposite(); 192 193 bool willWriteHTML(Document*, unsigned startLine); 194 void didWriteHTML(unsigned endLine); 195 196 void didInstallTimer(ExecutionContext*, int timerId, int timeout, bool singleShot); 197 void didRemoveTimer(ExecutionContext*, int timerId); 198 bool willFireTimer(ExecutionContext*, int timerId); 199 void didFireTimer(); 200 201 bool willDispatchXHRReadyStateChangeEvent(ExecutionContext*, XMLHttpRequest*); 202 void didDispatchXHRReadyStateChangeEvent(); 203 bool willDispatchXHRLoadEvent(ExecutionContext*, XMLHttpRequest*); 204 void didDispatchXHRLoadEvent(); 205 206 bool willEvaluateScript(Frame*, const String&, int); 207 void didEvaluateScript(); 208 209 void consoleTimeStamp(ExecutionContext*, const String& title); 210 void domContentLoadedEventFired(Frame*); 211 void loadEventFired(Frame*); 212 213 void consoleTime(ExecutionContext*, const String&); 214 void consoleTimeEnd(ExecutionContext*, const String&, ScriptState*); 215 void consoleTimeline(ExecutionContext*, const String& title, ScriptState*); 216 void consoleTimelineEnd(ExecutionContext*, const String& title, ScriptState*); 217 218 void didScheduleResourceRequest(Document*, const String& url); 219 void willSendRequest(unsigned long, DocumentLoader*, const ResourceRequest&, const ResourceResponse&, const FetchInitiatorInfo&); 220 void didReceiveResourceResponse(Frame*, unsigned long, DocumentLoader*, const ResourceResponse&, ResourceLoader*); 221 void didFinishLoading(unsigned long, DocumentLoader*, double monotonicFinishTime); 222 void didFailLoading(unsigned long identifier, DocumentLoader* loader, const ResourceError& error); 223 bool willReceiveResourceData(Frame*, unsigned long identifier, int length); 224 void didReceiveResourceData(); 225 226 void didRequestAnimationFrame(Document*, int callbackId); 227 void didCancelAnimationFrame(Document*, int callbackId); 228 bool willFireAnimationFrame(Document*, int callbackId); 229 void didFireAnimationFrame(); 230 231 void willProcessTask(); 232 void didProcessTask(); 233 234 void didCreateWebSocket(Document*, unsigned long identifier, const KURL&, const String& protocol); 235 void willSendWebSocketHandshakeRequest(Document*, unsigned long identifier, const WebSocketHandshakeRequest&); 236 void didReceiveWebSocketHandshakeResponse(Document*, unsigned long identifier, const WebSocketHandshakeResponse&); 237 void didCloseWebSocket(Document*, unsigned long identifier); 238 239 void processGPUEvent(const GPUEvent&); 240 241 // ScriptGCEventListener methods. 242 virtual void didGC(double, double, size_t); 243 244 // PlatformInstrumentationClient methods. 245 virtual void willDecodeImage(const String& imageType) OVERRIDE; 246 virtual void didDecodeImage() OVERRIDE; 247 virtual void willResizeImage(bool shouldCache) OVERRIDE; 248 virtual void didResizeImage() OVERRIDE; 249 250 private: 251 252 friend class TimelineRecordStack; 253 254 InspectorTimelineAgent(InstrumentingAgents*, InspectorPageAgent*, InspectorMemoryAgent*, InspectorDOMAgent*, InspectorOverlay*, InspectorCompositeState*, InspectorType, InspectorClient*); 255 256 // Trace event handlers 257 void onBeginImplSideFrame(const TraceEventDispatcher::TraceEvent&); 258 void onPaintSetupBegin(const TraceEventDispatcher::TraceEvent&); 259 void onPaintSetupEnd(const TraceEventDispatcher::TraceEvent&); 260 void onRasterTaskBegin(const TraceEventDispatcher::TraceEvent&); 261 void onRasterTaskEnd(const TraceEventDispatcher::TraceEvent&); 262 void onImageDecodeBegin(const TraceEventDispatcher::TraceEvent&); 263 void onImageDecodeEnd(const TraceEventDispatcher::TraceEvent&); 264 void onLayerDeleted(const TraceEventDispatcher::TraceEvent&); 265 void onDrawLazyPixelRef(const TraceEventDispatcher::TraceEvent&); 266 void onDecodeLazyPixelRefBegin(const TraceEventDispatcher::TraceEvent&); 267 void onDecodeLazyPixelRefEnd(const TraceEventDispatcher::TraceEvent&); 268 void onActivateLayerTree(const TraceEventDispatcher::TraceEvent&); 269 void onLazyPixelRefDeleted(const TraceEventDispatcher::TraceEvent&); 270 271 void didFinishLoadingResource(unsigned long, bool didFail, double finishTime, Frame*); 272 273 void sendEvent(PassRefPtr<JSONObject>); 274 void appendRecord(PassRefPtr<JSONObject> data, const String& type, bool captureCallStack, Frame*); 275 void pushCurrentRecord(PassRefPtr<JSONObject>, const String& type, bool captureCallStack, Frame*, bool hasLowLevelDetails = false); 276 TimelineThreadState& threadState(ThreadIdentifier); 277 278 void setDOMCounters(TypeBuilder::Timeline::TimelineEvent*); 279 void setFrameIdentifier(JSONObject* record, Frame*); 280 void populateImageDetails(JSONObject* data, const RenderImage&); 281 282 void pushGCEventRecords(); 283 284 void didCompleteCurrentRecord(const String& type); 285 void unwindRecordStack(); 286 287 void commitFrameRecord(); 288 289 void addRecordToTimeline(PassRefPtr<JSONObject>); 290 void innerAddRecordToTimeline(PassRefPtr<JSONObject>); 291 void clearRecordStack(); 292 PassRefPtr<JSONObject> createRecordForEvent(const TraceEventDispatcher::TraceEvent&, const String& type, PassRefPtr<JSONObject> data = 0); 293 294 void localToPageQuad(const RenderObject& renderer, const LayoutRect&, FloatQuad*); 295 long long nodeId(Node*); 296 long long nodeId(RenderObject*); 297 void releaseNodeIds(); 298 299 double timestamp(); 300 Page* page(); 301 302 bool isStarted(); 303 void innerStart(); 304 void innerStop(bool fromConsole); 305 306 InspectorPageAgent* m_pageAgent; 307 InspectorMemoryAgent* m_memoryAgent; 308 InspectorDOMAgent* m_domAgent; 309 InspectorFrontend::Timeline* m_frontend; 310 InspectorClient* m_client; 311 InspectorOverlay* m_overlay; 312 InspectorType m_inspectorType; 313 314 int m_id; 315 unsigned long long m_layerTreeId; 316 317 TimelineTimeConverter m_timeConverter; 318 int m_maxCallStackDepth; 319 320 Vector<TimelineRecordEntry> m_recordStack; 321 RefPtr<TypeBuilder::Array<TypeBuilder::Timeline::TimelineEvent> > m_bufferedEvents; 322 Vector<String> m_consoleTimelines; 323 324 typedef Vector<TimelineGCEvent> GCEvents; 325 GCEvents m_gcEvents; 326 unsigned m_platformInstrumentationClientInstalledAtStackDepth; 327 RefPtr<JSONObject> m_pendingFrameRecord; 328 RefPtr<JSONObject> m_pendingGPURecord; 329 typedef HashMap<unsigned long long, TimelineImageInfo> PixelRefToImageInfoMap; 330 PixelRefToImageInfoMap m_pixelRefToImageInfo; 331 RenderImage* m_imageBeingPainted; 332 HashMap<unsigned long long, long long> m_layerToNodeMap; 333 double m_paintSetupStart; 334 double m_paintSetupEnd; 335 RefPtr<JSONObject> m_gpuTask; 336 unsigned m_styleRecalcElementCounter; 337 typedef HashMap<ThreadIdentifier, TimelineThreadState> ThreadStateMap; 338 ThreadStateMap m_threadStates; 339 bool m_mayEmitFirstPaint; 340 }; 341 342 } // namespace WebCore 343 344 #endif // !defined(InspectorTimelineAgent_h) 345