1/* 2* Copyright (C) 2009 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 "InspectorTimelineAgent.h" 33 34#if ENABLE(INSPECTOR) 35 36#include "Event.h" 37#include "InspectorFrontend.h" 38#include "IntRect.h" 39#include "ResourceRequest.h" 40#include "ResourceResponse.h" 41#include "TimelineRecordFactory.h" 42 43#include <wtf/CurrentTime.h> 44 45namespace WebCore { 46 47InspectorTimelineAgent::InspectorTimelineAgent(InspectorFrontend* frontend) 48 : m_frontend(frontend) 49{ 50 ASSERT(m_frontend); 51} 52 53InspectorTimelineAgent::~InspectorTimelineAgent() 54{ 55} 56 57void InspectorTimelineAgent::willDispatchEvent(const Event& event) 58{ 59 pushCurrentRecord(TimelineRecordFactory::createEventDispatchData(m_frontend, event), 60 EventDispatchTimelineRecordType); 61} 62 63void InspectorTimelineAgent::didDispatchEvent() 64{ 65 didCompleteCurrentRecord(EventDispatchTimelineRecordType); 66} 67 68void InspectorTimelineAgent::willLayout() 69{ 70 pushCurrentRecord(m_frontend->newScriptObject(), LayoutTimelineRecordType); 71} 72 73void InspectorTimelineAgent::didLayout() 74{ 75 didCompleteCurrentRecord(LayoutTimelineRecordType); 76} 77 78void InspectorTimelineAgent::willRecalculateStyle() 79{ 80 pushCurrentRecord(m_frontend->newScriptObject(), RecalculateStylesTimelineRecordType); 81} 82 83void InspectorTimelineAgent::didRecalculateStyle() 84{ 85 didCompleteCurrentRecord(RecalculateStylesTimelineRecordType); 86} 87 88void InspectorTimelineAgent::willPaint(const IntRect& rect) 89{ 90 pushCurrentRecord(TimelineRecordFactory::createPaintData(m_frontend, rect), PaintTimelineRecordType); 91} 92 93void InspectorTimelineAgent::didPaint() 94{ 95 didCompleteCurrentRecord(PaintTimelineRecordType); 96} 97 98void InspectorTimelineAgent::willWriteHTML(unsigned int length, unsigned int startLine) 99{ 100 pushCurrentRecord(TimelineRecordFactory::createParseHTMLData(m_frontend, length, startLine), ParseHTMLTimelineRecordType); 101} 102 103void InspectorTimelineAgent::didWriteHTML(unsigned int endLine) 104{ 105 if (!m_recordStack.isEmpty()) { 106 TimelineRecordEntry entry = m_recordStack.last(); 107 entry.data.set("endLine", endLine); 108 didCompleteCurrentRecord(ParseHTMLTimelineRecordType); 109 } 110} 111 112void InspectorTimelineAgent::didInstallTimer(int timerId, int timeout, bool singleShot) 113{ 114 ScriptObject record = TimelineRecordFactory::createGenericRecord(m_frontend, currentTimeInMilliseconds()); 115 record.set("data", TimelineRecordFactory::createTimerInstallData(m_frontend, timerId, timeout, singleShot)); 116 addRecordToTimeline(record, TimerInstallTimelineRecordType); 117} 118 119void InspectorTimelineAgent::didRemoveTimer(int timerId) 120{ 121 ScriptObject record = TimelineRecordFactory::createGenericRecord(m_frontend, currentTimeInMilliseconds()); 122 record.set("data", TimelineRecordFactory::createGenericTimerData(m_frontend, timerId)); 123 addRecordToTimeline(record, TimerRemoveTimelineRecordType); 124} 125 126void InspectorTimelineAgent::willFireTimer(int timerId) 127{ 128 pushCurrentRecord(TimelineRecordFactory::createGenericTimerData(m_frontend, timerId), TimerFireTimelineRecordType); 129} 130 131void InspectorTimelineAgent::didFireTimer() 132{ 133 didCompleteCurrentRecord(TimerFireTimelineRecordType); 134} 135 136void InspectorTimelineAgent::willChangeXHRReadyState(const String& url, int readyState) 137{ 138 pushCurrentRecord(TimelineRecordFactory::createXHRReadyStateChangeData(m_frontend, url, readyState), XHRReadyStateChangeRecordType); 139} 140 141void InspectorTimelineAgent::didChangeXHRReadyState() 142{ 143 didCompleteCurrentRecord(XHRReadyStateChangeRecordType); 144} 145 146void InspectorTimelineAgent::willLoadXHR(const String& url) 147{ 148 pushCurrentRecord(TimelineRecordFactory::createXHRLoadData(m_frontend, url), XHRLoadRecordType); 149} 150 151void InspectorTimelineAgent::didLoadXHR() 152{ 153 didCompleteCurrentRecord(XHRLoadRecordType); 154} 155 156void InspectorTimelineAgent::willEvaluateScript(const String& url, int lineNumber) 157{ 158 pushCurrentRecord(TimelineRecordFactory::createEvaluateScriptData(m_frontend, url, lineNumber), EvaluateScriptTimelineRecordType); 159} 160 161void InspectorTimelineAgent::didEvaluateScript() 162{ 163 didCompleteCurrentRecord(EvaluateScriptTimelineRecordType); 164} 165 166void InspectorTimelineAgent::willSendResourceRequest(unsigned long identifier, bool isMainResource, 167 const ResourceRequest& request) 168{ 169 ScriptObject record = TimelineRecordFactory::createGenericRecord(m_frontend, currentTimeInMilliseconds()); 170 record.set("data", TimelineRecordFactory::createResourceSendRequestData(m_frontend, identifier, isMainResource, request)); 171 record.set("type", ResourceSendRequestTimelineRecordType); 172 m_frontend->addRecordToTimeline(record); 173} 174 175void InspectorTimelineAgent::didReceiveResourceResponse(unsigned long identifier, const ResourceResponse& response) 176{ 177 ScriptObject record = TimelineRecordFactory::createGenericRecord(m_frontend, currentTimeInMilliseconds()); 178 record.set("data", TimelineRecordFactory::createResourceReceiveResponseData(m_frontend, identifier, response)); 179 record.set("type", ResourceReceiveResponseTimelineRecordType); 180 m_frontend->addRecordToTimeline(record); 181} 182 183void InspectorTimelineAgent::didFinishLoadingResource(unsigned long identifier, bool didFail) 184{ 185 ScriptObject record = TimelineRecordFactory::createGenericRecord(m_frontend, currentTimeInMilliseconds()); 186 record.set("data", TimelineRecordFactory::createResourceFinishData(m_frontend, identifier, didFail)); 187 record.set("type", ResourceFinishTimelineRecordType); 188 m_frontend->addRecordToTimeline(record); 189} 190 191void InspectorTimelineAgent::didMarkTimeline(const String& message) 192{ 193 ScriptObject record = TimelineRecordFactory::createGenericRecord(m_frontend, currentTimeInMilliseconds()); 194 record.set("data", TimelineRecordFactory::createMarkTimelineData(m_frontend, message)); 195 addRecordToTimeline(record, MarkTimelineRecordType); 196} 197 198void InspectorTimelineAgent::reset() 199{ 200 m_recordStack.clear(); 201} 202 203void InspectorTimelineAgent::resetFrontendProxyObject(InspectorFrontend* frontend) 204{ 205 ASSERT(frontend); 206 reset(); 207 m_frontend = frontend; 208} 209 210void InspectorTimelineAgent::addRecordToTimeline(ScriptObject record, TimelineRecordType type) 211{ 212 record.set("type", type); 213 if (m_recordStack.isEmpty()) 214 m_frontend->addRecordToTimeline(record); 215 else { 216 TimelineRecordEntry parent = m_recordStack.last(); 217 parent.children.set(parent.children.length(), record); 218 } 219} 220 221void InspectorTimelineAgent::didCompleteCurrentRecord(TimelineRecordType type) 222{ 223 // An empty stack could merely mean that the timeline agent was turned on in the middle of 224 // an event. Don't treat as an error. 225 if (!m_recordStack.isEmpty()) { 226 TimelineRecordEntry entry = m_recordStack.last(); 227 m_recordStack.removeLast(); 228 ASSERT(entry.type == type); 229 entry.record.set("data", entry.data); 230 entry.record.set("children", entry.children); 231 entry.record.set("endTime", currentTimeInMilliseconds()); 232 addRecordToTimeline(entry.record, type); 233 } 234} 235 236double InspectorTimelineAgent::currentTimeInMilliseconds() 237{ 238 return currentTime() * 1000.0; 239} 240 241void InspectorTimelineAgent::pushCurrentRecord(ScriptObject data, TimelineRecordType type) 242{ 243 m_recordStack.append(TimelineRecordEntry(TimelineRecordFactory::createGenericRecord(m_frontend, currentTimeInMilliseconds()), data, m_frontend->newScriptArray(), type)); 244} 245 246} // namespace WebCore 247 248#endif // ENABLE(INSPECTOR) 249