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 45 namespace WebCore { 46 47 InspectorTimelineAgent::InspectorTimelineAgent(InspectorFrontend* frontend) 48 : m_frontend(frontend) 49 { 50 ASSERT(m_frontend); 51 } 52 53 InspectorTimelineAgent::~InspectorTimelineAgent() 54 { 55 } 56 57 void InspectorTimelineAgent::willDispatchEvent(const Event& event) 58 { 59 pushCurrentRecord(TimelineRecordFactory::createEventDispatchData(m_frontend, event), 60 EventDispatchTimelineRecordType); 61 } 62 63 void InspectorTimelineAgent::didDispatchEvent() 64 { 65 didCompleteCurrentRecord(EventDispatchTimelineRecordType); 66 } 67 68 void InspectorTimelineAgent::willLayout() 69 { 70 pushCurrentRecord(m_frontend->newScriptObject(), LayoutTimelineRecordType); 71 } 72 73 void InspectorTimelineAgent::didLayout() 74 { 75 didCompleteCurrentRecord(LayoutTimelineRecordType); 76 } 77 78 void InspectorTimelineAgent::willRecalculateStyle() 79 { 80 pushCurrentRecord(m_frontend->newScriptObject(), RecalculateStylesTimelineRecordType); 81 } 82 83 void InspectorTimelineAgent::didRecalculateStyle() 84 { 85 didCompleteCurrentRecord(RecalculateStylesTimelineRecordType); 86 } 87 88 void InspectorTimelineAgent::willPaint(const IntRect& rect) 89 { 90 pushCurrentRecord(TimelineRecordFactory::createPaintData(m_frontend, rect), PaintTimelineRecordType); 91 } 92 93 void InspectorTimelineAgent::didPaint() 94 { 95 didCompleteCurrentRecord(PaintTimelineRecordType); 96 } 97 98 void InspectorTimelineAgent::willWriteHTML(unsigned int length, unsigned int startLine) 99 { 100 pushCurrentRecord(TimelineRecordFactory::createParseHTMLData(m_frontend, length, startLine), ParseHTMLTimelineRecordType); 101 } 102 103 void 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 112 void 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 119 void 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 126 void InspectorTimelineAgent::willFireTimer(int timerId) 127 { 128 pushCurrentRecord(TimelineRecordFactory::createGenericTimerData(m_frontend, timerId), TimerFireTimelineRecordType); 129 } 130 131 void InspectorTimelineAgent::didFireTimer() 132 { 133 didCompleteCurrentRecord(TimerFireTimelineRecordType); 134 } 135 136 void InspectorTimelineAgent::willChangeXHRReadyState(const String& url, int readyState) 137 { 138 pushCurrentRecord(TimelineRecordFactory::createXHRReadyStateChangeData(m_frontend, url, readyState), XHRReadyStateChangeRecordType); 139 } 140 141 void InspectorTimelineAgent::didChangeXHRReadyState() 142 { 143 didCompleteCurrentRecord(XHRReadyStateChangeRecordType); 144 } 145 146 void InspectorTimelineAgent::willLoadXHR(const String& url) 147 { 148 pushCurrentRecord(TimelineRecordFactory::createXHRLoadData(m_frontend, url), XHRLoadRecordType); 149 } 150 151 void InspectorTimelineAgent::didLoadXHR() 152 { 153 didCompleteCurrentRecord(XHRLoadRecordType); 154 } 155 156 void InspectorTimelineAgent::willEvaluateScript(const String& url, int lineNumber) 157 { 158 pushCurrentRecord(TimelineRecordFactory::createEvaluateScriptData(m_frontend, url, lineNumber), EvaluateScriptTimelineRecordType); 159 } 160 161 void InspectorTimelineAgent::didEvaluateScript() 162 { 163 didCompleteCurrentRecord(EvaluateScriptTimelineRecordType); 164 } 165 166 void 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 175 void 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 183 void 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 191 void 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 198 void InspectorTimelineAgent::reset() 199 { 200 m_recordStack.clear(); 201 } 202 203 void InspectorTimelineAgent::resetFrontendProxyObject(InspectorFrontend* frontend) 204 { 205 ASSERT(frontend); 206 reset(); 207 m_frontend = frontend; 208 } 209 210 void 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 221 void 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 236 double InspectorTimelineAgent::currentTimeInMilliseconds() 237 { 238 return currentTime() * 1000.0; 239 } 240 241 void 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