Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: Source/core/inspector/AsyncCallStackTracker.cpp

Issue 114033002: DevTools: Capture async stacks for event listeners. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: construct event description Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 15 matching lines...) Expand all
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 #include "config.h" 31 #include "config.h"
32 #include "core/inspector/AsyncCallStackTracker.h" 32 #include "core/inspector/AsyncCallStackTracker.h"
33 33
34 #include "core/dom/ContextLifecycleObserver.h" 34 #include "core/dom/ContextLifecycleObserver.h"
35 #include "core/dom/ExecutionContext.h" 35 #include "core/dom/ExecutionContext.h"
36 #include "core/events/EventTarget.h"
37 #include "core/events/RegisteredEventListener.h"
38 #include "wtf/text/StringBuilder.h"
36 39
37 namespace WebCore { 40 namespace WebCore {
38 41
39 class AsyncCallStackTracker::ExecutionContextData : public ContextLifecycleObser ver { 42 class AsyncCallStackTracker::ExecutionContextData : public ContextLifecycleObser ver {
40 WTF_MAKE_FAST_ALLOCATED; 43 WTF_MAKE_FAST_ALLOCATED;
41 public: 44 public:
45 typedef std::pair<RegisteredEventListener, RefPtr<AsyncCallChain> > EventLis tenerAsyncCallChain;
46 typedef Vector<EventListenerAsyncCallChain, 1> EventListenerAsyncCallChainVe ctor;
47 typedef HashMap<AtomicString, EventListenerAsyncCallChainVector> EventListen erAsyncCallChainVectorHashMap;
48
42 ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu tionContext) 49 ExecutionContextData(AsyncCallStackTracker* tracker, ExecutionContext* execu tionContext)
43 : ContextLifecycleObserver(executionContext) 50 : ContextLifecycleObserver(executionContext)
44 , m_tracker(tracker) 51 , m_tracker(tracker)
45 { 52 {
46 } 53 }
47 54
48 virtual void contextDestroyed() OVERRIDE 55 virtual void contextDestroyed() OVERRIDE
49 { 56 {
50 m_tracker->contextDestroyed(executionContext()); 57 m_tracker->contextDestroyed(executionContext());
51 ContextLifecycleObserver::contextDestroyed(); 58 ContextLifecycleObserver::contextDestroyed();
52 } 59 }
53 60
61 void add(EventTarget* eventTarget, const AtomicString& eventType, const Even tListenerAsyncCallChain& item)
62 {
63 HashMap<EventTarget*, EventListenerAsyncCallChainVectorHashMap>::iterato r it = m_eventTargetCallChains.find(eventTarget);
64 if (it == m_eventTargetCallChains.end())
65 it = m_eventTargetCallChains.set(eventTarget, EventListenerAsyncCall ChainVectorHashMap()).iterator;
66 EventListenerAsyncCallChainVectorHashMap& map = it->value;
67 EventListenerAsyncCallChainVectorHashMap::iterator it2 = map.find(eventT ype);
68 if (it2 == map.end())
69 it2 = map.set(eventType, EventListenerAsyncCallChainVector()).iterat or;
70 it2->value.append(item);
71 }
72
73 void remove(EventTarget* eventTarget, const AtomicString& eventType, const R egisteredEventListener& item)
74 {
75 get(eventTarget, eventType, item, true);
76 }
77
78 PassRefPtr<AsyncCallChain> get(EventTarget* eventTarget, const AtomicString& eventType, const RegisteredEventListener& item, bool remove = false)
79 {
80 HashMap<EventTarget*, EventListenerAsyncCallChainVectorHashMap>::iterato r it = m_eventTargetCallChains.find(eventTarget);
81 if (it == m_eventTargetCallChains.end())
82 return 0;
83 EventListenerAsyncCallChainVectorHashMap& map = it->value;
84 EventListenerAsyncCallChainVectorHashMap::iterator it2 = map.find(eventT ype);
85 if (it2 == map.end())
86 return 0;
87 RefPtr<AsyncCallChain> result;
88 EventListenerAsyncCallChainVector& vector = it2->value;
89 for (size_t i = 0; i < vector.size(); ++i) {
90 if (vector[i].first == item) {
91 result = vector[i].second;
92 if (remove) {
93 vector.remove(i);
94 if (vector.isEmpty())
95 map.remove(it2);
96 if (map.isEmpty())
97 m_eventTargetCallChains.remove(it);
98 }
99 break;
100 }
101 }
102 return result.release();
103 }
104
54 private: 105 private:
55 friend class AsyncCallStackTracker; 106 friend class AsyncCallStackTracker;
56 AsyncCallStackTracker* m_tracker; 107 AsyncCallStackTracker* m_tracker;
57 HashSet<int> m_intervalTimerIds; 108 HashSet<int> m_intervalTimerIds;
58 HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains; 109 HashMap<int, RefPtr<AsyncCallChain> > m_timerCallChains;
59 HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains; 110 HashMap<int, RefPtr<AsyncCallChain> > m_animationFrameCallChains;
111 HashMap<EventTarget*, EventListenerAsyncCallChainVectorHashMap> m_eventTarge tCallChains;
60 }; 112 };
61 113
62 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const String& description, const ScriptValue& callFrames) 114 AsyncCallStackTracker::AsyncCallStack::AsyncCallStack(const String& description, const ScriptValue& callFrames)
63 : m_description(description) 115 : m_description(description)
64 , m_callFrames(callFrames) 116 , m_callFrames(callFrames)
65 { 117 {
66 } 118 }
67 119
68 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack() 120 AsyncCallStackTracker::AsyncCallStack::~AsyncCallStack()
69 { 121 {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
161 { 213 {
162 ASSERT(context); 214 ASSERT(context);
163 if (!isEnabled()) 215 if (!isEnabled())
164 return; 216 return;
165 ASSERT(callbackId > 0); 217 ASSERT(callbackId > 0);
166 ASSERT(!m_currentAsyncCallChain); 218 ASSERT(!m_currentAsyncCallChain);
167 if (ExecutionContextData* data = m_executionContextDataMap.get(context)) 219 if (ExecutionContextData* data = m_executionContextDataMap.get(context))
168 m_currentAsyncCallChain = data->m_animationFrameCallChains.take(callback Id); 220 m_currentAsyncCallChain = data->m_animationFrameCallChains.take(callback Id);
169 } 221 }
170 222
223 void AsyncCallStackTracker::didAddEventListener(EventTarget* eventTarget, const AtomicString& eventType, EventListener* listener, bool useCapture, const ScriptV alue& callFrames)
224 {
225 ASSERT(eventTarget->executionContext());
226 ASSERT(isEnabled());
227 if (!validateCallFrames(callFrames))
228 return;
229
230 StringBuilder description;
231 description.append(eventTarget->interfaceName());
232 if (!description.isEmpty())
233 description.append(".");
234 if (listener->isAttribute()) {
235 description.append("on");
236 description.append(eventType);
237 } else {
238 description.append("addEventListener(\"");
239 description.append(eventType);
240 description.append("\")");
241 }
242
243 ExecutionContextData* data = createContextDataIfNeeded(eventTarget->executio nContext());
244 data->add(eventTarget, eventType, std::make_pair(RegisteredEventListener(lis tener, useCapture), createAsyncCallChain(description.toString(), callFrames)));
245 }
246
247 void AsyncCallStackTracker::didRemoveEventListener(EventTarget* eventTarget, con st AtomicString& eventType, EventListener* listener, bool useCapture)
248 {
249 ASSERT(eventTarget->executionContext());
250 if (!isEnabled())
251 return;
252 if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget-> executionContext()))
253 data->remove(eventTarget, eventType, RegisteredEventListener(listener, u seCapture));
254 }
255
256 void AsyncCallStackTracker::didRemoveAllEventListeners(EventTarget* eventTarget)
257 {
258 ASSERT(eventTarget->executionContext());
259 if (!isEnabled())
260 return;
261 if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget-> executionContext()))
262 data->m_eventTargetCallChains.remove(eventTarget);
263 }
264
265 void AsyncCallStackTracker::willHandleEvent(EventTarget* eventTarget, const Atom icString& eventType, EventListener* listener, bool useCapture)
266 {
267 ASSERT(eventTarget->executionContext());
268 if (!isEnabled())
269 return;
270 // FIXME: Handle events being fired synchronously right after they are added .
271 // ASSERT(!m_currentAsyncCallChain);
272 if (ExecutionContextData* data = m_executionContextDataMap.get(eventTarget-> executionContext()))
273 m_currentAsyncCallChain = data->get(eventTarget, eventType, RegisteredEv entListener(listener, useCapture));
274 }
275
171 void AsyncCallStackTracker::didFireAsyncCall() 276 void AsyncCallStackTracker::didFireAsyncCall()
172 { 277 {
173 m_currentAsyncCallChain = 0; 278 m_currentAsyncCallChain = 0;
174 } 279 }
175 280
176 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA syncCallChain(const String& description, const ScriptValue& callFrames) 281 PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA syncCallChain(const String& description, const ScriptValue& callFrames)
177 { 282 {
178 ASSERT(isEnabled()); 283 ASSERT(isEnabled());
179 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr acker::AsyncCallChain()); 284 RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncC allStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTr acker::AsyncCallChain());
180 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); 285 ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 { 319 {
215 m_currentAsyncCallChain = 0; 320 m_currentAsyncCallChain = 0;
216 Vector<ExecutionContextData*> contextsData; 321 Vector<ExecutionContextData*> contextsData;
217 copyValuesToVector(m_executionContextDataMap, contextsData); 322 copyValuesToVector(m_executionContextDataMap, contextsData);
218 m_executionContextDataMap.clear(); 323 m_executionContextDataMap.clear();
219 for (Vector<ExecutionContextData*>::const_iterator it = contextsData.begin() ; it != contextsData.end(); ++it) 324 for (Vector<ExecutionContextData*>::const_iterator it = contextsData.begin() ; it != contextsData.end(); ++it)
220 delete *it; 325 delete *it;
221 } 326 }
222 327
223 } // namespace WebCore 328 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698