Chromium Code Reviews| Index: Source/core/inspector/AsyncCallStackTracker.cpp |
| diff --git a/Source/core/inspector/AsyncCallStackTracker.cpp b/Source/core/inspector/AsyncCallStackTracker.cpp |
| index cb4d83a9eb15b8d10562964f0924ced021fb6f47..8c8819a05b88cae129d4f5f047848711eee9652c 100644 |
| --- a/Source/core/inspector/AsyncCallStackTracker.cpp |
| +++ b/Source/core/inspector/AsyncCallStackTracker.cpp |
| @@ -40,6 +40,7 @@ |
| #include "core/events/EventTarget.h" |
| #include "core/xml/XMLHttpRequest.h" |
| #include "core/xml/XMLHttpRequestUpload.h" |
| +#include "platform/AsyncFileSystemCallbacks.h" |
| #include "wtf/text/StringBuilder.h" |
| #include "wtf/text/StringHash.h" |
| #include <v8.h> |
| @@ -51,6 +52,7 @@ static const char setIntervalName[] = "setInterval"; |
| static const char requestAnimationFrameName[] = "requestAnimationFrame"; |
| static const char xhrSendName[] = "XMLHttpRequest.send"; |
| static const char enqueueMutationRecordName[] = "Mutation"; |
| +static const char fileSystemName[] = "FileSystem"; |
| } |
| @@ -83,6 +85,7 @@ public: |
| HashMap<EventTarget*, RefPtr<AsyncCallChain> > m_xhrCallChains; |
| HashMap<MutationObserver*, RefPtr<AsyncCallChain> > m_mutationObserverCallChains; |
| HashMap<ExecutionContextTask*, RefPtr<AsyncCallChain> > m_executionContextTaskCallChains; |
| + HashMap<AsyncFileSystemCallbacks*, RefPtr<AsyncCallChain> > m_fileSystemCallChains; |
| HashMap<String, RefPtr<AsyncCallChain> > m_v8AsyncTaskCallChains; |
| }; |
| @@ -327,6 +330,38 @@ void AsyncCallStackTracker::willPerformExecutionContextTask(ExecutionContext* co |
| setCurrentAsyncCallChain(context, nullptr); |
| } |
| +void AsyncCallStackTracker::didEnqueueAsyncFileSystemCallback(ExecutionContext* context, AsyncFileSystemCallbacks* callback, const ScriptValue& callFrames) |
| +{ |
| + ASSERT(context); |
| + ASSERT(isEnabled()); |
| + if (!validateCallFrames(callFrames)) |
| + return; |
| + ExecutionContextData* data = createContextDataIfNeeded(context); |
| + data->m_fileSystemCallChains.set(callback, createAsyncCallChain(fileSystemName, callFrames)); |
| +} |
| + |
| +void AsyncCallStackTracker::didRemoveAsyncFileSystemCallback(ExecutionContext* context, AsyncFileSystemCallbacks* callback) |
| +{ |
| + ASSERT(context); |
| + ASSERT(isEnabled()); |
| + if (ExecutionContextData* data = m_executionContextDataMap.get(context)) |
| + data->m_fileSystemCallChains.remove(callback); |
| +} |
| + |
| +void AsyncCallStackTracker::willHandleAsyncFileSystemCallback(ExecutionContext* context, AsyncFileSystemCallbacks* callback, bool hasMore) |
| +{ |
| + ASSERT(context); |
| + ASSERT(isEnabled()); |
| + if (ExecutionContextData* data = m_executionContextDataMap.get(context)) { |
| + if (hasMore) |
| + setCurrentAsyncCallChain(context, data->m_fileSystemCallChains.get(callback)); |
|
yurys
2014/07/14 14:55:54
style: consider extracting setCurrentAsyncCallChai
|
| + else |
| + setCurrentAsyncCallChain(context, data->m_fileSystemCallChains.take(callback)); |
| + } else { |
| + setCurrentAsyncCallChain(context, nullptr); |
| + } |
| +} |
| + |
| static String makeV8AsyncTaskUniqueId(const String& eventName, int id) |
| { |
| StringBuilder builder; |
| @@ -360,11 +395,28 @@ void AsyncCallStackTracker::didFireAsyncCall() |
| clearCurrentAsyncCallChain(); |
| } |
| +void AsyncCallStackTracker::willRescheduleAsyncCallChain() |
| +{ |
| + ASSERT(isEnabled()); |
| + if (!m_rescheduledAsyncCallChain) |
| + m_rescheduleNextAsyncCallChain = true; |
| +} |
| + |
| +void AsyncCallStackTracker::didRescheduleAsyncCallChain() |
| +{ |
| + ASSERT(isEnabled()); |
| + m_rescheduleNextAsyncCallChain = false; |
| + m_rescheduledAsyncCallChain.clear(); |
| +} |
| + |
| PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createAsyncCallChain(const String& description, const ScriptValue& callFrames) |
| { |
| + // Check if we should propogate the async call stack chain. |
| + if (m_rescheduledAsyncCallChain) |
| + return m_rescheduledAsyncCallChain; |
| if (callFrames.isEmpty()) { |
| ASSERT(m_currentAsyncCallChain); |
| - return m_currentAsyncCallChain; // Propogate async call stack chain. |
| + return m_currentAsyncCallChain; |
| } |
| RefPtr<AsyncCallChain> chain = adoptRef(m_currentAsyncCallChain ? new AsyncCallStackTracker::AsyncCallChain(*m_currentAsyncCallChain) : new AsyncCallStackTracker::AsyncCallChain()); |
| ensureMaxAsyncCallChainDepth(chain.get(), m_maxAsyncCallStackDepth - 1); |
| @@ -374,6 +426,10 @@ PassRefPtr<AsyncCallStackTracker::AsyncCallChain> AsyncCallStackTracker::createA |
| void AsyncCallStackTracker::setCurrentAsyncCallChain(ExecutionContext* context, PassRefPtr<AsyncCallChain> chain) |
| { |
| + if (m_rescheduleNextAsyncCallChain) { |
| + m_rescheduleNextAsyncCallChain = false; |
| + m_rescheduledAsyncCallChain = chain.get(); |
| + } |
| if (V8RecursionScope::recursionLevel(toIsolate(context))) { |
| if (m_currentAsyncCallChain) |
| ++m_nestedAsyncCallCount; |
| @@ -401,7 +457,7 @@ void AsyncCallStackTracker::ensureMaxAsyncCallChainDepth(AsyncCallChain* chain, |
| bool AsyncCallStackTracker::validateCallFrames(const ScriptValue& callFrames) |
| { |
| - return !callFrames.isEmpty() || m_currentAsyncCallChain; |
| + return !callFrames.isEmpty() || m_currentAsyncCallChain || m_rescheduledAsyncCallChain; |
| } |
| AsyncCallStackTracker::ExecutionContextData* AsyncCallStackTracker::createContextDataIfNeeded(ExecutionContext* context) |
| @@ -418,6 +474,8 @@ void AsyncCallStackTracker::clear() |
| { |
| m_currentAsyncCallChain.clear(); |
| m_nestedAsyncCallCount = 0; |
| + m_rescheduleNextAsyncCallChain = false; |
| + m_rescheduledAsyncCallChain.clear(); |
| ExecutionContextDataMap copy; |
| m_executionContextDataMap.swap(copy); |
| for (ExecutionContextDataMap::const_iterator it = copy.begin(); it != copy.end(); ++it) |