Home | History | Annotate | Download | only in inspector
      1 /*
      2 * Copyright (C) 2013 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 #include "config.h"
     32 #include "core/inspector/InspectorTimelineAgent.h"
     33 
     34 #include "core/events/Event.h"
     35 #include "core/frame/LocalDOMWindow.h"
     36 #include "core/frame/FrameConsole.h"
     37 #include "core/frame/FrameHost.h"
     38 #include "core/frame/FrameView.h"
     39 #include "core/frame/LocalFrame.h"
     40 #include "core/inspector/ConsoleMessage.h"
     41 #include "core/inspector/IdentifiersFactory.h"
     42 #include "core/inspector/InspectorClient.h"
     43 #include "core/inspector/InspectorCounters.h"
     44 #include "core/inspector/InspectorInstrumentation.h"
     45 #include "core/inspector/InspectorLayerTreeAgent.h"
     46 #include "core/inspector/InspectorNodeIds.h"
     47 #include "core/inspector/InspectorOverlay.h"
     48 #include "core/inspector/InspectorPageAgent.h"
     49 #include "core/inspector/InspectorState.h"
     50 #include "core/inspector/InstrumentingAgents.h"
     51 #include "core/inspector/ScriptCallStack.h"
     52 #include "core/inspector/TimelineRecordFactory.h"
     53 #include "core/inspector/TraceEventDispatcher.h"
     54 #include "core/loader/DocumentLoader.h"
     55 #include "core/page/Page.h"
     56 #include "core/rendering/RenderObject.h"
     57 #include "core/rendering/RenderView.h"
     58 #include "core/xml/XMLHttpRequest.h"
     59 #include "platform/TraceEvent.h"
     60 #include "platform/graphics/DeferredImageDecoder.h"
     61 #include "platform/graphics/GraphicsLayer.h"
     62 #include "platform/network/ResourceRequest.h"
     63 #include "wtf/CurrentTime.h"
     64 #include "wtf/DateMath.h"
     65 
     66 namespace blink {
     67 
     68 namespace TimelineAgentState {
     69 static const char enabled[] = "enabled";
     70 static const char started[] = "started";
     71 static const char startedFromProtocol[] = "startedFromProtocol";
     72 static const char timelineMaxCallStackDepth[] = "timelineMaxCallStackDepth";
     73 static const char includeCounters[] = "includeCounters";
     74 static const char includeGPUEvents[] = "includeGPUEvents";
     75 static const char bufferEvents[] = "bufferEvents";
     76 static const char liveEvents[] = "liveEvents";
     77 }
     78 
     79 // Must be kept in sync with WebInspector.TimelineModel.RecordType in TimelineModel.js
     80 namespace TimelineRecordType {
     81 static const char Program[] = "Program";
     82 
     83 static const char EventDispatch[] = "EventDispatch";
     84 static const char ScheduleStyleRecalculation[] = "ScheduleStyleRecalculation";
     85 static const char RecalculateStyles[] = "RecalculateStyles";
     86 static const char InvalidateLayout[] = "InvalidateLayout";
     87 static const char Layout[] = "Layout";
     88 static const char UpdateLayerTree[] = "UpdateLayerTree";
     89 static const char Paint[] = "Paint";
     90 static const char ScrollLayer[] = "ScrollLayer";
     91 static const char ResizeImage[] = "ResizeImage";
     92 static const char CompositeLayers[] = "CompositeLayers";
     93 
     94 static const char ParseHTML[] = "ParseHTML";
     95 
     96 static const char TimerInstall[] = "TimerInstall";
     97 static const char TimerRemove[] = "TimerRemove";
     98 static const char TimerFire[] = "TimerFire";
     99 
    100 static const char EvaluateScript[] = "EvaluateScript";
    101 
    102 static const char MarkLoad[] = "MarkLoad";
    103 static const char MarkDOMContent[] = "MarkDOMContent";
    104 static const char MarkFirstPaint[] = "MarkFirstPaint";
    105 
    106 static const char TimeStamp[] = "TimeStamp";
    107 static const char ConsoleTime[] = "ConsoleTime";
    108 
    109 static const char ResourceSendRequest[] = "ResourceSendRequest";
    110 static const char ResourceReceiveResponse[] = "ResourceReceiveResponse";
    111 static const char ResourceReceivedData[] = "ResourceReceivedData";
    112 static const char ResourceFinish[] = "ResourceFinish";
    113 
    114 static const char XHRReadyStateChange[] = "XHRReadyStateChange";
    115 static const char XHRLoad[] = "XHRLoad";
    116 
    117 static const char FunctionCall[] = "FunctionCall";
    118 static const char GCEvent[] = "GCEvent";
    119 
    120 static const char UpdateCounters[] = "UpdateCounters";
    121 
    122 static const char RequestAnimationFrame[] = "RequestAnimationFrame";
    123 static const char CancelAnimationFrame[] = "CancelAnimationFrame";
    124 static const char FireAnimationFrame[] = "FireAnimationFrame";
    125 
    126 static const char WebSocketCreate[] = "WebSocketCreate";
    127 static const char WebSocketSendHandshakeRequest[] = "WebSocketSendHandshakeRequest";
    128 static const char WebSocketReceiveHandshakeResponse[] = "WebSocketReceiveHandshakeResponse";
    129 static const char WebSocketDestroy[] = "WebSocketDestroy";
    130 
    131 static const char RequestMainThreadFrame[] = "RequestMainThreadFrame";
    132 static const char ActivateLayerTree[] = "ActivateLayerTree";
    133 static const char DrawFrame[] = "DrawFrame";
    134 static const char BeginFrame[] = "BeginFrame";
    135 static const char DecodeImage[] = "DecodeImage";
    136 static const char GPUTask[] = "GPUTask";
    137 static const char Rasterize[] = "Rasterize";
    138 static const char PaintSetup[] = "PaintSetup";
    139 
    140 static const char EmbedderCallback[] = "EmbedderCallback";
    141 }
    142 
    143 using TypeBuilder::Timeline::TimelineEvent;
    144 
    145 class InspectorTimelineAgentTraceEventListener : public TraceEventDispatcher::TraceEventListener {
    146 public:
    147     typedef void (InspectorTimelineAgent::*TraceEventHandlerMethod)(const TraceEventDispatcher::TraceEvent&);
    148     static PassOwnPtrWillBeRawPtr<InspectorTimelineAgentTraceEventListener> create(InspectorTimelineAgent* instance, TraceEventHandlerMethod method)
    149     {
    150         return adoptPtrWillBeNoop(new InspectorTimelineAgentTraceEventListener(instance, method));
    151     }
    152     virtual void call(const TraceEventDispatcher::TraceEvent& event) OVERRIDE
    153     {
    154         (m_instance->*m_method)(event);
    155     }
    156     virtual void* target() OVERRIDE
    157     {
    158         return m_instance;
    159     }
    160     virtual void trace(Visitor* visitor) OVERRIDE
    161     {
    162         visitor->trace(m_instance);
    163         TraceEventDispatcher::TraceEventListener::trace(visitor);
    164     }
    165 
    166 private:
    167     InspectorTimelineAgentTraceEventListener(InspectorTimelineAgent* instance, TraceEventHandlerMethod method)
    168         : m_instance(instance)
    169         , m_method(method)
    170     {
    171     }
    172     RawPtrWillBeMember<InspectorTimelineAgent> m_instance;
    173     TraceEventHandlerMethod m_method;
    174 };
    175 
    176 struct TimelineRecordEntry {
    177     TimelineRecordEntry(PassRefPtr<TimelineEvent> record, PassRefPtr<JSONObject> data, PassRefPtr<TypeBuilder::Array<TimelineEvent> > children, const String& type)
    178         : record(record)
    179         , data(data)
    180         , children(children)
    181         , type(type)
    182         , skipWhenUnbalanced(false)
    183     {
    184     }
    185     RefPtr<TimelineEvent> record;
    186     RefPtr<JSONObject> data;
    187     RefPtr<TypeBuilder::Array<TimelineEvent> > children;
    188     String type;
    189     bool skipWhenUnbalanced;
    190 };
    191 
    192 class TimelineRecordStack {
    193     DISALLOW_ALLOCATION();
    194 private:
    195     struct Entry {
    196         Entry(PassRefPtr<TimelineEvent> record, const String& type)
    197             : record(record)
    198             , children(TypeBuilder::Array<TimelineEvent>::create())
    199 #if ENABLE(ASSERT)
    200             , type(type)
    201 #endif
    202         {
    203         }
    204 
    205         RefPtr<TimelineEvent> record;
    206         RefPtr<TypeBuilder::Array<TimelineEvent> > children;
    207 #if ENABLE(ASSERT)
    208         String type;
    209 #endif
    210     };
    211 
    212 public:
    213     TimelineRecordStack() : m_timelineAgent(nullptr) { }
    214     explicit TimelineRecordStack(InspectorTimelineAgent*);
    215 
    216     void addScopedRecord(PassRefPtr<TimelineEvent> record, const String& type);
    217     void closeScopedRecord(double endTime);
    218     void addInstantRecord(PassRefPtr<TimelineEvent> record);
    219 
    220 #if ENABLE(ASSERT)
    221     bool isOpenRecordOfType(const String& type);
    222 #endif
    223 
    224     void trace(Visitor*);
    225 
    226 private:
    227     void send(PassRefPtr<JSONObject>);
    228 
    229     RawPtrWillBeMember<InspectorTimelineAgent> m_timelineAgent;
    230     Vector<Entry> m_stack;
    231 };
    232 
    233 struct TimelineThreadState {
    234     ALLOW_ONLY_INLINE_ALLOCATION();
    235 public:
    236     TimelineThreadState() { }
    237 
    238     TimelineThreadState(InspectorTimelineAgent* timelineAgent)
    239         : recordStack(timelineAgent)
    240         , inKnownLayerTask(false)
    241         , decodedPixelRefId(0)
    242     {
    243     }
    244 
    245     void trace(Visitor*);
    246 
    247     TimelineRecordStack recordStack;
    248     bool inKnownLayerTask;
    249     unsigned long long decodedPixelRefId;
    250 };
    251 
    252 struct TimelineImageInfo {
    253     int backendNodeId;
    254     String url;
    255 
    256     TimelineImageInfo() : backendNodeId(0) { }
    257     TimelineImageInfo(int backendNodeId, String url) : backendNodeId(backendNodeId), url(url) { }
    258 };
    259 
    260 static LocalFrame* frameForExecutionContext(ExecutionContext* context)
    261 {
    262     LocalFrame* frame = 0;
    263     if (context->isDocument())
    264         frame = toDocument(context)->frame();
    265     return frame;
    266 }
    267 
    268 static bool eventHasListeners(const AtomicString& eventType, LocalDOMWindow* window, Node* node, const EventPath& eventPath)
    269 {
    270     if (window && window->hasEventListeners(eventType))
    271         return true;
    272 
    273     if (node->hasEventListeners(eventType))
    274         return true;
    275 
    276     for (size_t i = 0; i < eventPath.size(); i++) {
    277         if (eventPath[i].node()->hasEventListeners(eventType))
    278             return true;
    279     }
    280 
    281     return false;
    282 }
    283 
    284 void InspectorTimelineAgent::didGC(double startTime, double endTime, size_t collectedBytesCount)
    285 {
    286     RefPtr<TimelineEvent> record = TimelineRecordFactory::createGenericRecord(
    287         startTime * msPerSecond,
    288         0,
    289         TimelineRecordType::GCEvent,
    290         TimelineRecordFactory::createGCEventData(collectedBytesCount));
    291     record->setEndTime(endTime * msPerSecond);
    292     double time = timestamp();
    293     addRecordToTimeline(record.release(), time);
    294     if (m_state->getBoolean(TimelineAgentState::includeCounters)) {
    295         addRecordToTimeline(createCountersUpdate(), time);
    296     }
    297 }
    298 
    299 InspectorTimelineAgent::~InspectorTimelineAgent()
    300 {
    301 }
    302 
    303 void InspectorTimelineAgent::trace(Visitor* visitor)
    304 {
    305     visitor->trace(m_pageAgent);
    306     visitor->trace(m_layerTreeAgent);
    307 #if ENABLE(OILPAN)
    308     visitor->trace(m_threadStates);
    309 #endif
    310     InspectorBaseAgent::trace(visitor);
    311 }
    312 
    313 void InspectorTimelineAgent::setFrontend(InspectorFrontend* frontend)
    314 {
    315     m_frontend = frontend->timeline();
    316 }
    317 
    318 void InspectorTimelineAgent::clearFrontend()
    319 {
    320     ErrorString error;
    321     stop(&error);
    322     disable(&error);
    323     m_frontend = 0;
    324 }
    325 
    326 void InspectorTimelineAgent::restore()
    327 {
    328     if (m_state->getBoolean(TimelineAgentState::startedFromProtocol)) {
    329         if (m_state->getBoolean(TimelineAgentState::bufferEvents))
    330             m_bufferedEvents = TypeBuilder::Array<TimelineEvent>::create();
    331 
    332         setLiveEvents(m_state->getString(TimelineAgentState::liveEvents));
    333         innerStart();
    334     } else if (isStarted()) {
    335         // Timeline was started from console.timeline, it is not restored.
    336         // Tell front-end timline is no longer collecting.
    337         m_state->setBoolean(TimelineAgentState::started, false);
    338         bool fromConsole = true;
    339         m_frontend->stopped(&fromConsole, nullptr);
    340     }
    341 }
    342 
    343 void InspectorTimelineAgent::enable(ErrorString*)
    344 {
    345     m_state->setBoolean(TimelineAgentState::enabled, true);
    346 }
    347 
    348 void InspectorTimelineAgent::disable(ErrorString*)
    349 {
    350     m_state->setBoolean(TimelineAgentState::enabled, false);
    351 }
    352 
    353 void InspectorTimelineAgent::start(ErrorString* errorString, const int* maxCallStackDepth, const bool* bufferEvents, const String* liveEvents, const bool* includeCounters, const bool* includeGPUEvents)
    354 {
    355     if (!m_frontend)
    356         return;
    357     m_state->setBoolean(TimelineAgentState::startedFromProtocol, true);
    358 
    359     if (isStarted()) {
    360         *errorString = "Timeline is already started";
    361         return;
    362     }
    363 
    364     if (maxCallStackDepth && *maxCallStackDepth >= 0)
    365         m_maxCallStackDepth = *maxCallStackDepth;
    366     else
    367         m_maxCallStackDepth = 5;
    368 
    369     if (asBool(bufferEvents)) {
    370         m_bufferedEvents = TypeBuilder::Array<TimelineEvent>::create();
    371         m_lastProgressTimestamp = timestamp();
    372     }
    373 
    374     if (liveEvents)
    375         setLiveEvents(*liveEvents);
    376 
    377     m_state->setLong(TimelineAgentState::timelineMaxCallStackDepth, m_maxCallStackDepth);
    378     m_state->setBoolean(TimelineAgentState::includeCounters, asBool(includeCounters));
    379     m_state->setBoolean(TimelineAgentState::includeGPUEvents, asBool(includeGPUEvents));
    380     m_state->setBoolean(TimelineAgentState::bufferEvents, asBool(bufferEvents));
    381     m_state->setString(TimelineAgentState::liveEvents, liveEvents ? *liveEvents : "");
    382 
    383     innerStart();
    384     bool fromConsole = false;
    385     m_frontend->started(&fromConsole);
    386 }
    387 
    388 bool InspectorTimelineAgent::isStarted()
    389 {
    390     return m_state->getBoolean(TimelineAgentState::started);
    391 }
    392 
    393 void InspectorTimelineAgent::innerStart()
    394 {
    395     if (m_overlay)
    396         m_overlay->startedRecordingProfile();
    397     m_state->setBoolean(TimelineAgentState::started, true);
    398     m_instrumentingAgents->setInspectorTimelineAgent(this);
    399     ScriptGCEvent::addEventListener(this);
    400     if (m_client) {
    401         TraceEventDispatcher* dispatcher = TraceEventDispatcher::instance();
    402         dispatcher->addListener(InstrumentationEvents::BeginFrame, TRACE_EVENT_PHASE_INSTANT, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onBeginImplSideFrame), m_client);
    403         dispatcher->addListener(InstrumentationEvents::PaintSetup, TRACE_EVENT_PHASE_BEGIN, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onPaintSetupBegin), m_client);
    404         dispatcher->addListener(InstrumentationEvents::PaintSetup, TRACE_EVENT_PHASE_END, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onPaintSetupEnd), m_client);
    405         dispatcher->addListener(InstrumentationEvents::RasterTask, TRACE_EVENT_PHASE_BEGIN, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onRasterTaskBegin), m_client);
    406         dispatcher->addListener(InstrumentationEvents::RasterTask, TRACE_EVENT_PHASE_END, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onRasterTaskEnd), m_client);
    407         dispatcher->addListener(InstrumentationEvents::Layer, TRACE_EVENT_PHASE_DELETE_OBJECT, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onLayerDeleted), m_client);
    408         dispatcher->addListener(InstrumentationEvents::RequestMainThreadFrame, TRACE_EVENT_PHASE_INSTANT, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onRequestMainThreadFrame), m_client);
    409         dispatcher->addListener(InstrumentationEvents::ActivateLayerTree, TRACE_EVENT_PHASE_INSTANT, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onActivateLayerTree), m_client);
    410         dispatcher->addListener(InstrumentationEvents::DrawFrame, TRACE_EVENT_PHASE_INSTANT, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onDrawFrame), m_client);
    411         dispatcher->addListener(PlatformInstrumentation::ImageDecodeEvent, TRACE_EVENT_PHASE_BEGIN, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onImageDecodeBegin), m_client);
    412         dispatcher->addListener(PlatformInstrumentation::ImageDecodeEvent, TRACE_EVENT_PHASE_END, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onImageDecodeEnd), m_client);
    413         dispatcher->addListener(PlatformInstrumentation::DrawLazyPixelRefEvent, TRACE_EVENT_PHASE_INSTANT, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onDrawLazyPixelRef), m_client);
    414         dispatcher->addListener(PlatformInstrumentation::DecodeLazyPixelRefEvent, TRACE_EVENT_PHASE_BEGIN, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onDecodeLazyPixelRefBegin), m_client);
    415         dispatcher->addListener(PlatformInstrumentation::DecodeLazyPixelRefEvent, TRACE_EVENT_PHASE_END, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onDecodeLazyPixelRefEnd), m_client);
    416         dispatcher->addListener(PlatformInstrumentation::LazyPixelRef, TRACE_EVENT_PHASE_DELETE_OBJECT, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onLazyPixelRefDeleted), m_client);
    417         dispatcher->addListener(InstrumentationEvents::EmbedderCallback, TRACE_EVENT_PHASE_BEGIN, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onEmbedderCallbackBegin), m_client);
    418         dispatcher->addListener(InstrumentationEvents::EmbedderCallback, TRACE_EVENT_PHASE_END, InspectorTimelineAgentTraceEventListener::create(this, &InspectorTimelineAgent::onEmbedderCallbackEnd), m_client);
    419 
    420         if (m_state->getBoolean(TimelineAgentState::includeGPUEvents)) {
    421             m_pendingGPURecord.clear();
    422             m_client->startGPUEventsRecording();
    423         }
    424     }
    425 }
    426 
    427 void InspectorTimelineAgent::stop(ErrorString* errorString)
    428 {
    429     m_state->setBoolean(TimelineAgentState::startedFromProtocol, false);
    430     m_state->setBoolean(TimelineAgentState::bufferEvents, false);
    431     m_state->setString(TimelineAgentState::liveEvents, "");
    432 
    433     if (!isStarted()) {
    434         *errorString = "Timeline was not started";
    435         return;
    436     }
    437     innerStop(false);
    438     m_liveEvents.clear();
    439 }
    440 
    441 void InspectorTimelineAgent::innerStop(bool fromConsole)
    442 {
    443     m_state->setBoolean(TimelineAgentState::started, false);
    444 
    445     if (m_client) {
    446         TraceEventDispatcher::instance()->removeAllListeners(this, m_client);
    447         if (m_state->getBoolean(TimelineAgentState::includeGPUEvents))
    448             m_client->stopGPUEventsRecording();
    449     }
    450     m_instrumentingAgents->setInspectorTimelineAgent(0);
    451     ScriptGCEvent::removeEventListener(this);
    452 
    453     clearRecordStack();
    454     m_threadStates.clear();
    455     m_gpuTask.clear();
    456     m_layerToNodeMap.clear();
    457     m_pixelRefToImageInfo.clear();
    458     m_imageBeingPainted = 0;
    459     m_paintSetupStart = 0;
    460     m_mayEmitFirstPaint = false;
    461 
    462     for (size_t i = 0; i < m_consoleTimelines.size(); ++i) {
    463         String message = String::format("Timeline '%s' terminated.", m_consoleTimelines[i].utf8().data());
    464         mainFrame()->console().addMessage(ConsoleMessage::create(JSMessageSource, DebugMessageLevel, message));
    465     }
    466     m_consoleTimelines.clear();
    467 
    468     m_frontend->stopped(&fromConsole, m_bufferedEvents.release());
    469     if (m_overlay)
    470         m_overlay->finishedRecordingProfile();
    471 }
    472 
    473 void InspectorTimelineAgent::didBeginFrame(int frameId)
    474 {
    475     TraceEventDispatcher::instance()->processBackgroundEvents();
    476     m_pendingFrameRecord = TimelineRecordFactory::createGenericRecord(timestamp(), 0, TimelineRecordType::BeginFrame, TimelineRecordFactory::createFrameData(frameId));
    477 }
    478 
    479 void InspectorTimelineAgent::didCancelFrame()
    480 {
    481     m_pendingFrameRecord.clear();
    482 }
    483 
    484 bool InspectorTimelineAgent::willCallFunction(ExecutionContext* context, int scriptId, const String& scriptName, int scriptLine)
    485 {
    486     pushCurrentRecord(TimelineRecordFactory::createFunctionCallData(scriptId, scriptName, scriptLine), TimelineRecordType::FunctionCall, true, frameForExecutionContext(context));
    487     return true;
    488 }
    489 
    490 void InspectorTimelineAgent::didCallFunction()
    491 {
    492     didCompleteCurrentRecord(TimelineRecordType::FunctionCall);
    493 }
    494 
    495 bool InspectorTimelineAgent::willDispatchEvent(Document* document, const Event& event, LocalDOMWindow* window, Node* node, const EventPath& eventPath)
    496 {
    497     if (!eventHasListeners(event.type(), window, node, eventPath))
    498         return false;
    499 
    500     pushCurrentRecord(TimelineRecordFactory::createEventDispatchData(event), TimelineRecordType::EventDispatch, false, document->frame());
    501     return true;
    502 }
    503 
    504 bool InspectorTimelineAgent::willDispatchEventOnWindow(const Event& event, LocalDOMWindow* window)
    505 {
    506     if (!window->hasEventListeners(event.type()))
    507         return false;
    508     pushCurrentRecord(TimelineRecordFactory::createEventDispatchData(event), TimelineRecordType::EventDispatch, false, window->frame());
    509     return true;
    510 }
    511 
    512 void InspectorTimelineAgent::didDispatchEvent()
    513 {
    514     didCompleteCurrentRecord(TimelineRecordType::EventDispatch);
    515 }
    516 
    517 void InspectorTimelineAgent::didDispatchEventOnWindow()
    518 {
    519     didDispatchEvent();
    520 }
    521 
    522 void InspectorTimelineAgent::didInvalidateLayout(LocalFrame* frame)
    523 {
    524     appendRecord(JSONObject::create(), TimelineRecordType::InvalidateLayout, true, frame);
    525 }
    526 
    527 bool InspectorTimelineAgent::willLayout(LocalFrame* frame)
    528 {
    529     bool isPartial;
    530     unsigned needsLayoutObjects;
    531     unsigned totalObjects;
    532     frame->countObjectsNeedingLayout(needsLayoutObjects, totalObjects, isPartial);
    533 
    534     pushCurrentRecord(TimelineRecordFactory::createLayoutData(needsLayoutObjects, totalObjects, isPartial), TimelineRecordType::Layout, true, frame);
    535     return true;
    536 }
    537 
    538 void InspectorTimelineAgent::didLayout(RenderObject* root)
    539 {
    540     if (m_recordStack.isEmpty())
    541         return;
    542     TimelineRecordEntry& entry = m_recordStack.last();
    543     ASSERT(entry.type == TimelineRecordType::Layout);
    544     Vector<FloatQuad> quads;
    545     root->absoluteQuads(quads);
    546     if (quads.size() >= 1)
    547         TimelineRecordFactory::setLayoutRoot(entry.data.get(), quads[0], nodeId(root));
    548     else
    549         ASSERT_NOT_REACHED();
    550     didCompleteCurrentRecord(TimelineRecordType::Layout);
    551 }
    552 
    553 void InspectorTimelineAgent::layerTreeDidChange()
    554 {
    555     ASSERT(!m_pendingLayerTreeData);
    556     m_pendingLayerTreeData = m_layerTreeAgent->buildLayerTree();
    557 }
    558 
    559 void InspectorTimelineAgent::willUpdateLayerTree()
    560 {
    561     pushCurrentRecord(JSONObject::create(), TimelineRecordType::UpdateLayerTree, false, 0);
    562 }
    563 
    564 void InspectorTimelineAgent::didUpdateLayerTree()
    565 {
    566     if (m_recordStack.isEmpty())
    567         return;
    568     TimelineRecordEntry& entry = m_recordStack.last();
    569     ASSERT(entry.type == TimelineRecordType::UpdateLayerTree);
    570     if (m_pendingLayerTreeData)
    571         TimelineRecordFactory::setLayerTreeData(entry.data.get(), m_pendingLayerTreeData.release());
    572     didCompleteCurrentRecord(TimelineRecordType::UpdateLayerTree);
    573 }
    574 
    575 void InspectorTimelineAgent::didScheduleStyleRecalculation(Document* document)
    576 {
    577     appendRecord(JSONObject::create(), TimelineRecordType::ScheduleStyleRecalculation, true, document->frame());
    578 }
    579 
    580 bool InspectorTimelineAgent::willRecalculateStyle(Document* document)
    581 {
    582     pushCurrentRecord(JSONObject::create(), TimelineRecordType::RecalculateStyles, true, document->frame());
    583     return true;
    584 }
    585 
    586 void InspectorTimelineAgent::didRecalculateStyle(int elementCount)
    587 {
    588     if (m_recordStack.isEmpty())
    589         return;
    590     TimelineRecordEntry& entry = m_recordStack.last();
    591     ASSERT(entry.type == TimelineRecordType::RecalculateStyles);
    592     TimelineRecordFactory::setStyleRecalcDetails(entry.data.get(), elementCount);
    593     didCompleteCurrentRecord(TimelineRecordType::RecalculateStyles);
    594 }
    595 
    596 void InspectorTimelineAgent::willPaint(RenderObject* renderer, const GraphicsLayer* graphicsLayer)
    597 {
    598     LocalFrame* frame = renderer->frame();
    599 
    600     TraceEventDispatcher::instance()->processBackgroundEvents();
    601     double paintSetupStart = m_paintSetupStart;
    602     m_paintSetupStart = 0;
    603     if (graphicsLayer) {
    604         int layerIdentifier = graphicsLayer->platformLayer()->id();
    605         int nodeIdentifier = nodeId(renderer);
    606         ASSERT(layerIdentifier && nodeIdentifier);
    607         m_layerToNodeMap.set(layerIdentifier, nodeIdentifier);
    608         if (paintSetupStart) {
    609             RefPtr<TimelineEvent> paintSetupRecord = TimelineRecordFactory::createGenericRecord(paintSetupStart, 0, TimelineRecordType::PaintSetup, TimelineRecordFactory::createLayerData(nodeIdentifier));
    610             paintSetupRecord->setEndTime(m_paintSetupEnd);
    611             addRecordToTimeline(paintSetupRecord, paintSetupStart);
    612         }
    613     }
    614     pushCurrentRecord(JSONObject::create(), TimelineRecordType::Paint, true, frame, true);
    615 }
    616 
    617 void InspectorTimelineAgent::didPaint(RenderObject* renderer, const GraphicsLayer* graphicsLayer, GraphicsContext*, const LayoutRect& clipRect)
    618 {
    619     TimelineRecordEntry& entry = m_recordStack.last();
    620     ASSERT(entry.type == TimelineRecordType::Paint);
    621     FloatQuad quad;
    622     localToPageQuad(*renderer, clipRect, &quad);
    623     int graphicsLayerId = graphicsLayer ? graphicsLayer->platformLayer()->id() : 0;
    624     TimelineRecordFactory::setPaintData(entry.data.get(), quad, nodeId(renderer), graphicsLayerId);
    625     didCompleteCurrentRecord(TimelineRecordType::Paint);
    626     if (m_mayEmitFirstPaint && !graphicsLayer) {
    627         m_mayEmitFirstPaint = false;
    628         appendRecord(JSONObject::create(), TimelineRecordType::MarkFirstPaint, false, 0);
    629     }
    630 }
    631 
    632 void InspectorTimelineAgent::willPaintImage(RenderImage* renderImage)
    633 {
    634     ASSERT(!m_imageBeingPainted);
    635     m_imageBeingPainted = renderImage;
    636 }
    637 
    638 void InspectorTimelineAgent::didPaintImage()
    639 {
    640     m_imageBeingPainted = 0;
    641 }
    642 
    643 void InspectorTimelineAgent::willScrollLayer(RenderObject* renderer)
    644 {
    645     pushCurrentRecord(TimelineRecordFactory::createLayerData(nodeId(renderer)), TimelineRecordType::ScrollLayer, false, renderer->frame());
    646 }
    647 
    648 void InspectorTimelineAgent::didScrollLayer()
    649 {
    650     didCompleteCurrentRecord(TimelineRecordType::ScrollLayer);
    651 }
    652 
    653 void InspectorTimelineAgent::willDecodeImage(const String& imageType)
    654 {
    655     RefPtr<JSONObject> data = TimelineRecordFactory::createDecodeImageData(imageType);
    656     if (m_imageBeingPainted)
    657         populateImageDetails(data.get(), *m_imageBeingPainted);
    658     pushCurrentRecord(data, TimelineRecordType::DecodeImage, true, 0);
    659 }
    660 
    661 void InspectorTimelineAgent::didDecodeImage()
    662 {
    663     didCompleteCurrentRecord(TimelineRecordType::DecodeImage);
    664 }
    665 
    666 void InspectorTimelineAgent::willResizeImage(bool shouldCache)
    667 {
    668     RefPtr<JSONObject> data = TimelineRecordFactory::createResizeImageData(shouldCache);
    669     if (m_imageBeingPainted)
    670         populateImageDetails(data.get(), *m_imageBeingPainted);
    671     pushCurrentRecord(data, TimelineRecordType::ResizeImage, true, 0);
    672 }
    673 
    674 void InspectorTimelineAgent::didResizeImage()
    675 {
    676     didCompleteCurrentRecord(TimelineRecordType::ResizeImage);
    677 }
    678 
    679 void InspectorTimelineAgent::willComposite()
    680 {
    681     pushCurrentRecord(JSONObject::create(), TimelineRecordType::CompositeLayers, false, 0);
    682 }
    683 
    684 void InspectorTimelineAgent::didComposite()
    685 {
    686     didCompleteCurrentRecord(TimelineRecordType::CompositeLayers);
    687     if (m_mayEmitFirstPaint) {
    688         m_mayEmitFirstPaint = false;
    689         appendRecord(JSONObject::create(), TimelineRecordType::MarkFirstPaint, false, 0);
    690     }
    691 }
    692 
    693 bool InspectorTimelineAgent::willWriteHTML(Document* document, unsigned startLine)
    694 {
    695     pushCurrentRecord(TimelineRecordFactory::createParseHTMLData(startLine), TimelineRecordType::ParseHTML, true, document->frame());
    696     return true;
    697 }
    698 
    699 void InspectorTimelineAgent::didWriteHTML(unsigned endLine)
    700 {
    701     if (!m_recordStack.isEmpty()) {
    702         TimelineRecordEntry& entry = m_recordStack.last();
    703         entry.data->setNumber("endLine", endLine);
    704         didCompleteCurrentRecord(TimelineRecordType::ParseHTML);
    705     }
    706 }
    707 
    708 void InspectorTimelineAgent::didInstallTimer(ExecutionContext* context, int timerId, int timeout, bool singleShot)
    709 {
    710     appendRecord(TimelineRecordFactory::createTimerInstallData(timerId, timeout, singleShot), TimelineRecordType::TimerInstall, true, frameForExecutionContext(context));
    711 }
    712 
    713 void InspectorTimelineAgent::didRemoveTimer(ExecutionContext* context, int timerId)
    714 {
    715     appendRecord(TimelineRecordFactory::createGenericTimerData(timerId), TimelineRecordType::TimerRemove, true, frameForExecutionContext(context));
    716 }
    717 
    718 bool InspectorTimelineAgent::willFireTimer(ExecutionContext* context, int timerId)
    719 {
    720     pushCurrentRecord(TimelineRecordFactory::createGenericTimerData(timerId), TimelineRecordType::TimerFire, false, frameForExecutionContext(context));
    721     return true;
    722 }
    723 
    724 void InspectorTimelineAgent::didFireTimer()
    725 {
    726     didCompleteCurrentRecord(TimelineRecordType::TimerFire);
    727 }
    728 
    729 bool InspectorTimelineAgent::willDispatchXHRReadyStateChangeEvent(ExecutionContext* context, XMLHttpRequest* request)
    730 {
    731     if (!request->hasEventListeners(EventTypeNames::readystatechange))
    732         return false;
    733     pushCurrentRecord(TimelineRecordFactory::createXHRReadyStateChangeData(request->url().string(), request->readyState()), TimelineRecordType::XHRReadyStateChange, false, frameForExecutionContext(context));
    734     return true;
    735 }
    736 
    737 void InspectorTimelineAgent::didDispatchXHRReadyStateChangeEvent()
    738 {
    739     didCompleteCurrentRecord(TimelineRecordType::XHRReadyStateChange);
    740 }
    741 
    742 bool InspectorTimelineAgent::willDispatchXHRLoadEvent(ExecutionContext* context, XMLHttpRequest* request)
    743 {
    744     if (!request->hasEventListeners(EventTypeNames::load))
    745         return false;
    746     pushCurrentRecord(TimelineRecordFactory::createXHRLoadData(request->url().string()), TimelineRecordType::XHRLoad, true, frameForExecutionContext(context));
    747     return true;
    748 }
    749 
    750 void InspectorTimelineAgent::didDispatchXHRLoadEvent()
    751 {
    752     didCompleteCurrentRecord(TimelineRecordType::XHRLoad);
    753 }
    754 
    755 bool InspectorTimelineAgent::willEvaluateScript(LocalFrame* frame, const String& url, int lineNumber)
    756 {
    757     pushCurrentRecord(TimelineRecordFactory::createEvaluateScriptData(url, lineNumber), TimelineRecordType::EvaluateScript, true, frame);
    758     return true;
    759 }
    760 
    761 void InspectorTimelineAgent::didEvaluateScript()
    762 {
    763     didCompleteCurrentRecord(TimelineRecordType::EvaluateScript);
    764 }
    765 
    766 void InspectorTimelineAgent::willSendRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request, const ResourceResponse&, const FetchInitiatorInfo&)
    767 {
    768     String requestId = IdentifiersFactory::requestId(identifier);
    769     appendRecord(TimelineRecordFactory::createResourceSendRequestData(requestId, request), TimelineRecordType::ResourceSendRequest, true, loader->frame());
    770 }
    771 
    772 void InspectorTimelineAgent::didReceiveData(LocalFrame* frame, unsigned long identifier, const char*, int, int encodedDataLength)
    773 {
    774     String requestId = IdentifiersFactory::requestId(identifier);
    775     appendRecord(TimelineRecordFactory::createReceiveResourceData(requestId, encodedDataLength), TimelineRecordType::ResourceReceivedData, false, frame);
    776 }
    777 
    778 void InspectorTimelineAgent::didReceiveResourceResponse(LocalFrame* frame, unsigned long identifier, DocumentLoader* loader, const ResourceResponse& response, ResourceLoader* resourceLoader)
    779 {
    780     String requestId = IdentifiersFactory::requestId(identifier);
    781     appendRecord(TimelineRecordFactory::createResourceReceiveResponseData(requestId, response), TimelineRecordType::ResourceReceiveResponse, false, 0);
    782 }
    783 
    784 void InspectorTimelineAgent::didFinishLoadingResource(unsigned long identifier, bool didFail, double finishTime)
    785 {
    786     appendRecord(TimelineRecordFactory::createResourceFinishData(IdentifiersFactory::requestId(identifier), didFail, finishTime), TimelineRecordType::ResourceFinish, false, 0);
    787 }
    788 
    789 void InspectorTimelineAgent::didFinishLoading(unsigned long identifier, DocumentLoader* loader, double monotonicFinishTime, int64_t)
    790 {
    791     didFinishLoadingResource(identifier, false, monotonicFinishTime * msPerSecond);
    792 }
    793 
    794 void InspectorTimelineAgent::didFailLoading(unsigned long identifier, const ResourceError& error)
    795 {
    796     didFinishLoadingResource(identifier, true, 0);
    797 }
    798 
    799 void InspectorTimelineAgent::consoleTimeStamp(ExecutionContext* context, const String& title)
    800 {
    801     appendRecord(TimelineRecordFactory::createTimeStampData(title), TimelineRecordType::TimeStamp, true, frameForExecutionContext(context));
    802 }
    803 
    804 void InspectorTimelineAgent::consoleTime(ExecutionContext* context, const String& message)
    805 {
    806     pushCurrentRecord(TimelineRecordFactory::createConsoleTimeData(message), TimelineRecordType::ConsoleTime, false, frameForExecutionContext(context));
    807     m_recordStack.last().skipWhenUnbalanced = true;
    808 }
    809 
    810 void InspectorTimelineAgent::consoleTimeEnd(ExecutionContext* context, const String& message, ScriptState*)
    811 {
    812     if (m_recordStack.last().type != TimelineRecordType::ConsoleTime)
    813         return;
    814     String originalMessage;
    815     if (m_recordStack.last().data->getString("message", &originalMessage) && message != originalMessage)
    816         return;
    817     // Only complete console.time that is balanced.
    818     didCompleteCurrentRecord(TimelineRecordType::ConsoleTime);
    819 }
    820 
    821 void InspectorTimelineAgent::consoleTimeline(ExecutionContext* context, const String& title, ScriptState* scriptState)
    822 {
    823     if (!m_state->getBoolean(TimelineAgentState::enabled))
    824         return;
    825 
    826     String message = String::format("Timeline '%s' started.", title.utf8().data());
    827 
    828     RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, DebugMessageLevel, message);
    829     consoleMessage->setScriptState(scriptState);
    830     mainFrame()->console().addMessage(consoleMessage.release());
    831     m_consoleTimelines.append(title);
    832     if (!isStarted()) {
    833         m_state->setBoolean(TimelineAgentState::bufferEvents, true);
    834         m_bufferedEvents = TypeBuilder::Array<TimelineEvent>::create();
    835 
    836         innerStart();
    837         bool fromConsole = true;
    838         m_frontend->started(&fromConsole);
    839     }
    840     appendRecord(TimelineRecordFactory::createTimeStampData(message), TimelineRecordType::TimeStamp, true, frameForExecutionContext(context));
    841 }
    842 
    843 void InspectorTimelineAgent::consoleTimelineEnd(ExecutionContext* context, const String& title, ScriptState* scriptState)
    844 {
    845     if (!m_state->getBoolean(TimelineAgentState::enabled))
    846         return;
    847 
    848     size_t index = m_consoleTimelines.find(title);
    849     if (index == kNotFound) {
    850         String message = String::format("Timeline '%s' was not started.", title.utf8().data());
    851         RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, DebugMessageLevel, message);
    852         consoleMessage->setScriptState(scriptState);
    853         mainFrame()->console().addMessage(consoleMessage.release());
    854         return;
    855     }
    856 
    857     String message = String::format("Timeline '%s' finished.", title.utf8().data());
    858     appendRecord(TimelineRecordFactory::createTimeStampData(message), TimelineRecordType::TimeStamp, true, frameForExecutionContext(context));
    859     m_consoleTimelines.remove(index);
    860     if (!m_consoleTimelines.size() && isStarted() && !m_state->getBoolean(TimelineAgentState::startedFromProtocol)) {
    861         unwindRecordStack();
    862         innerStop(true);
    863     }
    864     RefPtrWillBeRawPtr<ConsoleMessage> consoleMessage = ConsoleMessage::create(JSMessageSource, DebugMessageLevel, message);
    865     consoleMessage->setScriptState(scriptState);
    866     mainFrame()->console().addMessage(consoleMessage.release());
    867 }
    868 
    869 void InspectorTimelineAgent::domContentLoadedEventFired(LocalFrame* frame)
    870 {
    871     bool isMainFrame = frame && m_pageAgent && (frame == m_pageAgent->mainFrame());
    872     appendRecord(TimelineRecordFactory::createMarkData(isMainFrame), TimelineRecordType::MarkDOMContent, false, frame);
    873     if (isMainFrame)
    874         m_mayEmitFirstPaint = true;
    875 }
    876 
    877 void InspectorTimelineAgent::loadEventFired(LocalFrame* frame)
    878 {
    879     bool isMainFrame = frame && m_pageAgent && (frame == m_pageAgent->mainFrame());
    880     appendRecord(TimelineRecordFactory::createMarkData(isMainFrame), TimelineRecordType::MarkLoad, false, frame);
    881 }
    882 
    883 void InspectorTimelineAgent::didCommitLoad()
    884 {
    885     clearRecordStack();
    886 }
    887 
    888 void InspectorTimelineAgent::didRequestAnimationFrame(Document* document, int callbackId)
    889 {
    890     appendRecord(TimelineRecordFactory::createAnimationFrameData(callbackId), TimelineRecordType::RequestAnimationFrame, true, document->frame());
    891 }
    892 
    893 void InspectorTimelineAgent::didCancelAnimationFrame(Document* document, int callbackId)
    894 {
    895     appendRecord(TimelineRecordFactory::createAnimationFrameData(callbackId), TimelineRecordType::CancelAnimationFrame, true, document->frame());
    896 }
    897 
    898 bool InspectorTimelineAgent::willFireAnimationFrame(Document* document, int callbackId)
    899 {
    900     pushCurrentRecord(TimelineRecordFactory::createAnimationFrameData(callbackId), TimelineRecordType::FireAnimationFrame, false, document->frame());
    901     return true;
    902 }
    903 
    904 void InspectorTimelineAgent::didFireAnimationFrame()
    905 {
    906     didCompleteCurrentRecord(TimelineRecordType::FireAnimationFrame);
    907 }
    908 
    909 void InspectorTimelineAgent::willProcessTask()
    910 {
    911     pushCurrentRecord(JSONObject::create(), TimelineRecordType::Program, false, 0);
    912 }
    913 
    914 void InspectorTimelineAgent::didProcessTask()
    915 {
    916     didCompleteCurrentRecord(TimelineRecordType::Program);
    917 }
    918 
    919 void InspectorTimelineAgent::didCreateWebSocket(Document* document, unsigned long identifier, const KURL& url, const String& protocol)
    920 {
    921     appendRecord(TimelineRecordFactory::createWebSocketCreateData(identifier, url, protocol), TimelineRecordType::WebSocketCreate, true, document->frame());
    922 }
    923 
    924 void InspectorTimelineAgent::willSendWebSocketHandshakeRequest(Document* document, unsigned long identifier, const WebSocketHandshakeRequest*)
    925 {
    926     appendRecord(TimelineRecordFactory::createGenericWebSocketData(identifier), TimelineRecordType::WebSocketSendHandshakeRequest, true, document->frame());
    927 }
    928 
    929 void InspectorTimelineAgent::didReceiveWebSocketHandshakeResponse(Document* document, unsigned long identifier, const WebSocketHandshakeRequest*, const WebSocketHandshakeResponse*)
    930 {
    931     appendRecord(TimelineRecordFactory::createGenericWebSocketData(identifier), TimelineRecordType::WebSocketReceiveHandshakeResponse, false, document->frame());
    932 }
    933 
    934 void InspectorTimelineAgent::didCloseWebSocket(Document* document, unsigned long identifier)
    935 {
    936     appendRecord(TimelineRecordFactory::createGenericWebSocketData(identifier), TimelineRecordType::WebSocketDestroy, true, document->frame());
    937 }
    938 
    939 void InspectorTimelineAgent::onBeginImplSideFrame(const TraceEventDispatcher::TraceEvent& event)
    940 {
    941     unsigned long long layerTreeId = event.asUInt(InstrumentationEventArguments::LayerTreeId);
    942     if (layerTreeId != m_layerTreeId)
    943         return;
    944     TimelineThreadState& state = threadState(event.threadIdentifier());
    945     state.recordStack.addInstantRecord(createRecordForEvent(event, TimelineRecordType::BeginFrame, JSONObject::create()));
    946 }
    947 
    948 void InspectorTimelineAgent::onPaintSetupBegin(const TraceEventDispatcher::TraceEvent& event)
    949 {
    950     ASSERT(!m_paintSetupStart);
    951     m_paintSetupStart = event.timestamp() * msPerSecond;
    952 }
    953 
    954 void InspectorTimelineAgent::onPaintSetupEnd(const TraceEventDispatcher::TraceEvent& event)
    955 {
    956     ASSERT(m_paintSetupStart);
    957     m_paintSetupEnd = event.timestamp() * msPerSecond;
    958 }
    959 
    960 void InspectorTimelineAgent::onRasterTaskBegin(const TraceEventDispatcher::TraceEvent& event)
    961 {
    962     TimelineThreadState& state = threadState(event.threadIdentifier());
    963     unsigned long long layerId = event.asUInt(InstrumentationEventArguments::LayerId);
    964     ASSERT(layerId);
    965     if (!m_layerToNodeMap.contains(layerId))
    966         return;
    967     ASSERT(!state.inKnownLayerTask);
    968     state.inKnownLayerTask = true;
    969     double timestamp = event.timestamp() * msPerSecond;
    970     RefPtr<JSONObject> data = TimelineRecordFactory::createLayerData(m_layerToNodeMap.get(layerId));
    971     RefPtr<TimelineEvent> record = TimelineRecordFactory::createBackgroundRecord(timestamp, String::number(event.threadIdentifier()), TimelineRecordType::Rasterize, data);
    972     state.recordStack.addScopedRecord(record, TimelineRecordType::Rasterize);
    973 }
    974 
    975 void InspectorTimelineAgent::onRasterTaskEnd(const TraceEventDispatcher::TraceEvent& event)
    976 {
    977     TimelineThreadState& state = threadState(event.threadIdentifier());
    978     if (!state.inKnownLayerTask)
    979         return;
    980     ASSERT(state.recordStack.isOpenRecordOfType(TimelineRecordType::Rasterize));
    981     state.recordStack.closeScopedRecord(event.timestamp() * msPerSecond);
    982     state.inKnownLayerTask = false;
    983 }
    984 
    985 void InspectorTimelineAgent::onImageDecodeBegin(const TraceEventDispatcher::TraceEvent& event)
    986 {
    987     TimelineThreadState& state = threadState(event.threadIdentifier());
    988     if (!state.decodedPixelRefId && !state.inKnownLayerTask)
    989         return;
    990     TimelineImageInfo imageInfo;
    991     if (state.decodedPixelRefId) {
    992         PixelRefToImageInfoMap::const_iterator it = m_pixelRefToImageInfo.find(state.decodedPixelRefId);
    993         if (it != m_pixelRefToImageInfo.end())
    994             imageInfo = it->value;
    995         else
    996             ASSERT_NOT_REACHED();
    997     }
    998     RefPtr<JSONObject> data = JSONObject::create();
    999     TimelineRecordFactory::setImageDetails(data.get(), imageInfo.backendNodeId, imageInfo.url);
   1000     double timeestamp = event.timestamp() * msPerSecond;
   1001     state.recordStack.addScopedRecord(TimelineRecordFactory::createBackgroundRecord(timeestamp, String::number(event.threadIdentifier()), TimelineRecordType::DecodeImage, data), TimelineRecordType::DecodeImage);
   1002 }
   1003 
   1004 void InspectorTimelineAgent::onImageDecodeEnd(const TraceEventDispatcher::TraceEvent& event)
   1005 {
   1006     TimelineThreadState& state = threadState(event.threadIdentifier());
   1007     if (!state.decodedPixelRefId)
   1008         return;
   1009     ASSERT(state.recordStack.isOpenRecordOfType(TimelineRecordType::DecodeImage));
   1010     state.recordStack.closeScopedRecord(event.timestamp() * msPerSecond);
   1011 }
   1012 
   1013 void InspectorTimelineAgent::onRequestMainThreadFrame(const TraceEventDispatcher::TraceEvent& event)
   1014 {
   1015     unsigned long long layerTreeId = event.asUInt(InstrumentationEventArguments::LayerTreeId);
   1016     if (layerTreeId != m_layerTreeId)
   1017         return;
   1018     TimelineThreadState& state = threadState(event.threadIdentifier());
   1019     state.recordStack.addInstantRecord(createRecordForEvent(event, TimelineRecordType::RequestMainThreadFrame, JSONObject::create()));
   1020 }
   1021 
   1022 void InspectorTimelineAgent::onActivateLayerTree(const TraceEventDispatcher::TraceEvent& event)
   1023 {
   1024     unsigned long long layerTreeId = event.asUInt(InstrumentationEventArguments::LayerTreeId);
   1025     if (layerTreeId != m_layerTreeId)
   1026         return;
   1027     unsigned long long frameId = event.asUInt(InstrumentationEventArguments::FrameId);
   1028     TimelineThreadState& state = threadState(event.threadIdentifier());
   1029     state.recordStack.addInstantRecord(createRecordForEvent(event, TimelineRecordType::ActivateLayerTree, TimelineRecordFactory::createFrameData(frameId)));
   1030 }
   1031 
   1032 void InspectorTimelineAgent::onDrawFrame(const TraceEventDispatcher::TraceEvent& event)
   1033 {
   1034     unsigned long long layerTreeId = event.asUInt(InstrumentationEventArguments::LayerTreeId);
   1035     if (layerTreeId != m_layerTreeId)
   1036         return;
   1037     TimelineThreadState& state = threadState(event.threadIdentifier());
   1038     state.recordStack.addInstantRecord(createRecordForEvent(event, TimelineRecordType::DrawFrame, JSONObject::create()));
   1039 }
   1040 
   1041 void InspectorTimelineAgent::onLayerDeleted(const TraceEventDispatcher::TraceEvent& event)
   1042 {
   1043     unsigned long long id = event.id();
   1044     ASSERT(id);
   1045     m_layerToNodeMap.remove(id);
   1046 }
   1047 
   1048 void InspectorTimelineAgent::onDecodeLazyPixelRefBegin(const TraceEventDispatcher::TraceEvent& event)
   1049 {
   1050     TimelineThreadState& state = threadState(event.threadIdentifier());
   1051     ASSERT(!state.decodedPixelRefId);
   1052     unsigned long long pixelRefId = event.asUInt(PlatformInstrumentation::LazyPixelRef);
   1053     ASSERT(pixelRefId);
   1054     if (m_pixelRefToImageInfo.contains(pixelRefId))
   1055         state.decodedPixelRefId = pixelRefId;
   1056 }
   1057 
   1058 void InspectorTimelineAgent::onDecodeLazyPixelRefEnd(const TraceEventDispatcher::TraceEvent& event)
   1059 {
   1060     threadState(event.threadIdentifier()).decodedPixelRefId = 0;
   1061 }
   1062 
   1063 void InspectorTimelineAgent::onDrawLazyPixelRef(const TraceEventDispatcher::TraceEvent& event)
   1064 {
   1065     unsigned long long pixelRefId = event.asUInt(PlatformInstrumentation::LazyPixelRef);
   1066     ASSERT(pixelRefId);
   1067     if (!m_imageBeingPainted)
   1068         return;
   1069     String url;
   1070     if (const ImageResource* resource = m_imageBeingPainted->cachedImage())
   1071         url = resource->url().string();
   1072     m_pixelRefToImageInfo.set(pixelRefId, TimelineImageInfo(nodeId(m_imageBeingPainted->generatingNode()), url));
   1073 }
   1074 
   1075 void InspectorTimelineAgent::onLazyPixelRefDeleted(const TraceEventDispatcher::TraceEvent& event)
   1076 {
   1077     m_pixelRefToImageInfo.remove(event.id());
   1078 }
   1079 
   1080 void InspectorTimelineAgent::processGPUEvent(const GPUEvent& event)
   1081 {
   1082     double timelineTimestamp = event.timestamp * msPerSecond;
   1083     if (event.phase == GPUEvent::PhaseBegin) {
   1084         m_pendingGPURecord = TimelineRecordFactory::createBackgroundRecord(timelineTimestamp, "gpu", TimelineRecordType::GPUTask, TimelineRecordFactory::createGPUTaskData(event.foreign));
   1085     } else if (m_pendingGPURecord) {
   1086         m_pendingGPURecord->setEndTime(timelineTimestamp);
   1087         sendEvent(m_pendingGPURecord.release());
   1088         if (!event.foreign && m_state->getBoolean(TimelineAgentState::includeCounters)) {
   1089             RefPtr<TypeBuilder::Timeline::Counters> counters = TypeBuilder::Timeline::Counters::create();
   1090             counters->setGpuMemoryUsedKB(static_cast<double>(event.usedGPUMemoryBytes / 1024));
   1091             counters->setGpuMemoryLimitKB(static_cast<double>(event.limitGPUMemoryBytes / 1024));
   1092             sendEvent(TimelineRecordFactory::createBackgroundRecord(timelineTimestamp, "gpu", TimelineRecordType::UpdateCounters, counters.release()->asObject()));
   1093         }
   1094     }
   1095 }
   1096 
   1097 void InspectorTimelineAgent::onEmbedderCallbackBegin(const TraceEventDispatcher::TraceEvent& event)
   1098 {
   1099     TimelineThreadState& state = threadState(event.threadIdentifier());
   1100     double timestamp = event.timestamp() * msPerSecond;
   1101     RefPtr<JSONObject> data = TimelineRecordFactory::createEmbedderCallbackData(event.asString(InstrumentationEventArguments::CallbackName));
   1102     RefPtr<TimelineEvent> record = TimelineRecordFactory::createGenericRecord(timestamp, 0, TimelineRecordType::EmbedderCallback, data);
   1103     state.recordStack.addScopedRecord(record, TimelineRecordType::EmbedderCallback);
   1104 }
   1105 
   1106 void InspectorTimelineAgent::onEmbedderCallbackEnd(const TraceEventDispatcher::TraceEvent& event)
   1107 {
   1108     TimelineThreadState& state = threadState(event.threadIdentifier());
   1109     state.recordStack.closeScopedRecord(event.timestamp() * msPerSecond);
   1110 }
   1111 
   1112 void InspectorTimelineAgent::addRecordToTimeline(PassRefPtr<TimelineEvent> record, double ts)
   1113 {
   1114     commitFrameRecord();
   1115     innerAddRecordToTimeline(record);
   1116     if (m_bufferedEvents && ts - m_lastProgressTimestamp > 300) {
   1117         m_lastProgressTimestamp = ts;
   1118         m_frontend->progress(m_bufferedEvents->length());
   1119     }
   1120 }
   1121 
   1122 void InspectorTimelineAgent::innerAddRecordToTimeline(PassRefPtr<TimelineEvent> record)
   1123 {
   1124     if (m_recordStack.isEmpty()) {
   1125         TraceEventDispatcher::instance()->processBackgroundEvents();
   1126         sendEvent(record);
   1127     } else {
   1128         TimelineRecordEntry& parent = m_recordStack.last();
   1129         parent.children->addItem(record);
   1130         if (m_state->getBoolean(TimelineAgentState::includeCounters))
   1131             parent.children->addItem(createCountersUpdate());
   1132     }
   1133 }
   1134 
   1135 static size_t getUsedHeapSize()
   1136 {
   1137     HeapInfo info;
   1138     ScriptGCEvent::getHeapSize(info);
   1139     return info.usedJSHeapSize;
   1140 }
   1141 
   1142 PassRefPtr<TypeBuilder::Timeline::TimelineEvent> InspectorTimelineAgent::createCountersUpdate()
   1143 {
   1144     RefPtr<TypeBuilder::Timeline::Counters> counters = TypeBuilder::Timeline::Counters::create();
   1145     if (m_inspectorType == PageInspector) {
   1146         counters->setDocuments(InspectorCounters::counterValue(InspectorCounters::DocumentCounter));
   1147         counters->setNodes(InspectorCounters::counterValue(InspectorCounters::NodeCounter));
   1148         counters->setJsEventListeners(InspectorCounters::counterValue(InspectorCounters::JSEventListenerCounter));
   1149     }
   1150     counters->setJsHeapSizeUsed(static_cast<double>(getUsedHeapSize()));
   1151     return TimelineRecordFactory::createGenericRecord(timestamp(), 0, TimelineRecordType::UpdateCounters, counters.release()->asObject());
   1152 }
   1153 
   1154 void InspectorTimelineAgent::setFrameIdentifier(TimelineEvent* record, LocalFrame* frame)
   1155 {
   1156     if (!frame || !m_pageAgent)
   1157         return;
   1158     String frameId;
   1159     if (frame && m_pageAgent)
   1160         frameId = m_pageAgent->frameId(frame);
   1161     record->setFrameId(frameId);
   1162 }
   1163 
   1164 void InspectorTimelineAgent::populateImageDetails(JSONObject* data, const RenderImage& renderImage)
   1165 {
   1166     const ImageResource* resource = renderImage.cachedImage();
   1167     TimelineRecordFactory::setImageDetails(data, nodeId(renderImage.generatingNode()), resource ? resource->url().string() : "");
   1168 }
   1169 
   1170 void InspectorTimelineAgent::didCompleteCurrentRecord(const String& type)
   1171 {
   1172     // An empty stack could merely mean that the timeline agent was turned on in the middle of
   1173     // an event. Don't treat as an error.
   1174     if (!m_recordStack.isEmpty()) {
   1175         if (m_platformInstrumentationClientInstalledAtStackDepth == m_recordStack.size()) {
   1176             m_platformInstrumentationClientInstalledAtStackDepth = 0;
   1177             PlatformInstrumentation::setClient(0);
   1178         }
   1179 
   1180         TimelineRecordEntry entry = m_recordStack.last();
   1181         m_recordStack.removeLast();
   1182         while (entry.type != type && entry.skipWhenUnbalanced && !m_recordStack.isEmpty()) {
   1183             // Discard pending skippable entry, paste its children inplace.
   1184             if (entry.children)
   1185                 m_recordStack.last().children->concat(entry.children);
   1186             entry = m_recordStack.last();
   1187             m_recordStack.removeLast();
   1188         }
   1189         ASSERT(entry.type == type);
   1190         entry.record->setChildren(entry.children);
   1191         double ts = timestamp();
   1192         entry.record->setEndTime(ts);
   1193         addRecordToTimeline(entry.record, ts);
   1194     }
   1195 }
   1196 
   1197 void InspectorTimelineAgent::unwindRecordStack()
   1198 {
   1199     while (!m_recordStack.isEmpty()) {
   1200         TimelineRecordEntry& entry = m_recordStack.last();
   1201         didCompleteCurrentRecord(entry.type);
   1202     }
   1203 }
   1204 
   1205 InspectorTimelineAgent::InspectorTimelineAgent(InspectorPageAgent* pageAgent, InspectorLayerTreeAgent* layerTreeAgent,
   1206     InspectorOverlay* overlay, InspectorType type, InspectorClient* client)
   1207     : InspectorBaseAgent<InspectorTimelineAgent>("Timeline")
   1208     , m_pageAgent(pageAgent)
   1209     , m_layerTreeAgent(layerTreeAgent)
   1210     , m_frontend(0)
   1211     , m_client(client)
   1212     , m_overlay(overlay)
   1213     , m_inspectorType(type)
   1214     , m_id(1)
   1215     , m_layerTreeId(0)
   1216     , m_maxCallStackDepth(5)
   1217     , m_platformInstrumentationClientInstalledAtStackDepth(0)
   1218     , m_imageBeingPainted(0)
   1219     , m_paintSetupStart(0)
   1220     , m_mayEmitFirstPaint(false)
   1221     , m_lastProgressTimestamp(0)
   1222 {
   1223 }
   1224 
   1225 void InspectorTimelineAgent::appendRecord(PassRefPtr<JSONObject> data, const String& type, bool captureCallStack, LocalFrame* frame)
   1226 {
   1227     double ts = timestamp();
   1228     RefPtr<TimelineEvent> record = TimelineRecordFactory::createGenericRecord(ts, captureCallStack ? m_maxCallStackDepth : 0, type, data);
   1229     setFrameIdentifier(record.get(), frame);
   1230     addRecordToTimeline(record.release(), ts);
   1231 }
   1232 
   1233 void InspectorTimelineAgent::sendEvent(PassRefPtr<TimelineEvent> record)
   1234 {
   1235     RefPtr<TimelineEvent> retain = record;
   1236     if (m_bufferedEvents) {
   1237         m_bufferedEvents->addItem(retain);
   1238         if (!m_liveEvents.contains(TimelineRecordFactory::type(retain.get())))
   1239             return;
   1240     }
   1241     m_frontend->eventRecorded(retain.release());
   1242 }
   1243 
   1244 void InspectorTimelineAgent::pushCurrentRecord(PassRefPtr<JSONObject> data, const String& type, bool captureCallStack, LocalFrame* frame, bool hasLowLevelDetails)
   1245 {
   1246     commitFrameRecord();
   1247     RefPtr<TimelineEvent> record = TimelineRecordFactory::createGenericRecord(timestamp(), captureCallStack ? m_maxCallStackDepth : 0, type, data.get());
   1248     setFrameIdentifier(record.get(), frame);
   1249     m_recordStack.append(TimelineRecordEntry(record.release(), data, TypeBuilder::Array<TimelineEvent>::create(), type));
   1250     if (hasLowLevelDetails && !m_platformInstrumentationClientInstalledAtStackDepth && !PlatformInstrumentation::hasClient()) {
   1251         m_platformInstrumentationClientInstalledAtStackDepth = m_recordStack.size();
   1252         PlatformInstrumentation::setClient(this);
   1253     }
   1254 }
   1255 
   1256 TimelineThreadState& InspectorTimelineAgent::threadState(ThreadIdentifier thread)
   1257 {
   1258     ThreadStateMap::iterator it = m_threadStates.find(thread);
   1259     if (it != m_threadStates.end())
   1260         return it->value;
   1261     return m_threadStates.add(thread, TimelineThreadState(this)).storedValue->value;
   1262 }
   1263 
   1264 void InspectorTimelineAgent::commitFrameRecord()
   1265 {
   1266     if (!m_pendingFrameRecord)
   1267         return;
   1268     innerAddRecordToTimeline(m_pendingFrameRecord.release());
   1269 }
   1270 
   1271 void InspectorTimelineAgent::clearRecordStack()
   1272 {
   1273     if (m_platformInstrumentationClientInstalledAtStackDepth) {
   1274         m_platformInstrumentationClientInstalledAtStackDepth = 0;
   1275         PlatformInstrumentation::setClient(0);
   1276     }
   1277     m_pendingFrameRecord.clear();
   1278     m_recordStack.clear();
   1279     m_id++;
   1280 }
   1281 
   1282 void InspectorTimelineAgent::localToPageQuad(const RenderObject& renderer, const LayoutRect& rect, FloatQuad* quad)
   1283 {
   1284     LocalFrame* frame = renderer.frame();
   1285     FrameView* view = frame->view();
   1286     FloatQuad absolute = renderer.localToAbsoluteQuad(FloatQuad(rect));
   1287     quad->setP1(view->contentsToRootView(roundedIntPoint(absolute.p1())));
   1288     quad->setP2(view->contentsToRootView(roundedIntPoint(absolute.p2())));
   1289     quad->setP3(view->contentsToRootView(roundedIntPoint(absolute.p3())));
   1290     quad->setP4(view->contentsToRootView(roundedIntPoint(absolute.p4())));
   1291 }
   1292 
   1293 long long InspectorTimelineAgent::nodeId(Node* node)
   1294 {
   1295     return node ? InspectorNodeIds::idForNode(node)  : 0;
   1296 }
   1297 
   1298 long long InspectorTimelineAgent::nodeId(RenderObject* renderer)
   1299 {
   1300     return InspectorNodeIds::idForNode(renderer->generatingNode());
   1301 }
   1302 
   1303 double InspectorTimelineAgent::timestamp()
   1304 {
   1305     return WTF::monotonicallyIncreasingTime() * msPerSecond;
   1306 }
   1307 
   1308 LocalFrame* InspectorTimelineAgent::mainFrame() const
   1309 {
   1310     if (!m_pageAgent)
   1311         return 0;
   1312     return m_pageAgent->mainFrame();
   1313 }
   1314 
   1315 PassRefPtr<TimelineEvent> InspectorTimelineAgent::createRecordForEvent(const TraceEventDispatcher::TraceEvent& event, const String& type, PassRefPtr<JSONObject> data)
   1316 {
   1317     double timeestamp = event.timestamp() * msPerSecond;
   1318     return TimelineRecordFactory::createBackgroundRecord(timeestamp, String::number(event.threadIdentifier()), type, data);
   1319 }
   1320 
   1321 void InspectorTimelineAgent::setLiveEvents(const String& liveEvents)
   1322 {
   1323     m_liveEvents.clear();
   1324     if (liveEvents.isNull() || liveEvents.isEmpty())
   1325         return;
   1326     Vector<String> eventList;
   1327     liveEvents.split(',', eventList);
   1328     for (Vector<String>::iterator it = eventList.begin(); it != eventList.end(); ++it)
   1329         m_liveEvents.add(*it);
   1330 }
   1331 
   1332 TimelineRecordStack::TimelineRecordStack(InspectorTimelineAgent* timelineAgent)
   1333     : m_timelineAgent(timelineAgent)
   1334 {
   1335 }
   1336 
   1337 void TimelineRecordStack::addScopedRecord(PassRefPtr<TimelineEvent> record, const String& type)
   1338 {
   1339     m_stack.append(Entry(record, type));
   1340 }
   1341 
   1342 void TimelineRecordStack::closeScopedRecord(double endTime)
   1343 {
   1344     if (m_stack.isEmpty())
   1345         return;
   1346     Entry last = m_stack.last();
   1347     m_stack.removeLast();
   1348     last.record->setEndTime(endTime);
   1349     if (last.children->length())
   1350         last.record->setChildren(last.children);
   1351     addInstantRecord(last.record);
   1352 }
   1353 
   1354 void TimelineRecordStack::addInstantRecord(PassRefPtr<TimelineEvent> record)
   1355 {
   1356     if (m_stack.isEmpty())
   1357         m_timelineAgent->sendEvent(record);
   1358     else
   1359         m_stack.last().children->addItem(record);
   1360 }
   1361 
   1362 #if ENABLE(ASSERT)
   1363 bool TimelineRecordStack::isOpenRecordOfType(const String& type)
   1364 {
   1365     return !m_stack.isEmpty() && m_stack.last().type == type;
   1366 }
   1367 #endif
   1368 
   1369 void TimelineRecordStack::trace(Visitor* visitor)
   1370 {
   1371     visitor->trace(m_timelineAgent);
   1372 }
   1373 
   1374 void TimelineThreadState::trace(Visitor* visitor)
   1375 {
   1376     visitor->trace(recordStack);
   1377 }
   1378 
   1379 } // namespace blink
   1380