| Index: Source/core/xmlhttprequest/XMLHttpRequest.cpp
|
| diff --git a/Source/core/xmlhttprequest/XMLHttpRequest.cpp b/Source/core/xmlhttprequest/XMLHttpRequest.cpp
|
| index 065d9e10784c780b857c63125bad758d95b958e8..fce174ac9fb5dfa9ecf9b40f9eb54edb85b0fd9d 100644
|
| --- a/Source/core/xmlhttprequest/XMLHttpRequest.cpp
|
| +++ b/Source/core/xmlhttprequest/XMLHttpRequest.cpp
|
| @@ -75,12 +75,33 @@ namespace blink {
|
|
|
| DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XMLHttpRequest"));
|
|
|
| -static bool isSetCookieHeader(const AtomicString& name)
|
| +namespace {
|
| +
|
| +// This class protects the wrapper of the associated XMLHttpRequest object
|
| +// via hasPendingActivity method which returns true if
|
| +// m_eventDispatchRecursionLevel is positive.
|
| +class ScopedEventDispatchProtect final {
|
| +public:
|
| + explicit ScopedEventDispatchProtect(int* level) : m_level(level)
|
| + {
|
| + ++*m_level;
|
| + }
|
| + ~ScopedEventDispatchProtect()
|
| + {
|
| + ASSERT(*m_level > 0);
|
| + --*m_level;
|
| + }
|
| +
|
| +private:
|
| + int* const m_level;
|
| +};
|
| +
|
| +bool isSetCookieHeader(const AtomicString& name)
|
| {
|
| return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set-cookie2");
|
| }
|
|
|
| -static void replaceCharsetInMediaType(String& mediaType, const String& charsetValue)
|
| +void replaceCharsetInMediaType(String& mediaType, const String& charsetValue)
|
| {
|
| unsigned pos = 0, len = 0;
|
|
|
| @@ -99,7 +120,7 @@ static void replaceCharsetInMediaType(String& mediaType, const String& charsetVa
|
| }
|
| }
|
|
|
| -static void logConsoleError(ExecutionContext* context, const String& message)
|
| +void logConsoleError(ExecutionContext* context, const String& message)
|
| {
|
| if (!context)
|
| return;
|
| @@ -108,6 +129,8 @@ static void logConsoleError(ExecutionContext* context, const String& message)
|
| context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message));
|
| }
|
|
|
| +} // namespace
|
| +
|
| using Result = WebDataConsumerHandle::Result;
|
|
|
| // ReadableStreamSource is the underlying source for the response stream of
|
| @@ -308,6 +331,7 @@ XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOri
|
| , m_progressEventThrottle(this)
|
| , m_responseTypeCode(ResponseTypeDefault)
|
| , m_securityOrigin(securityOrigin)
|
| + , m_eventDispatchRecursionLevel(0)
|
| , m_async(true)
|
| , m_includeCredentials(false)
|
| , m_parsedResponse(false)
|
| @@ -1114,7 +1138,7 @@ bool XMLHttpRequest::internalAbort()
|
| // If abort() called internalAbort() and a nested open() ended up
|
| // clearing the error flag, but didn't send(), make sure the error
|
| // flag is still set.
|
| - bool newLoadStarted = hasPendingActivity();
|
| + bool newLoadStarted = m_loader;
|
| if (!newLoadStarted)
|
| m_error = true;
|
|
|
| @@ -1179,10 +1203,6 @@ void XMLHttpRequest::handleNetworkError()
|
| long long expectedLength = m_response.expectedContentLength();
|
| long long receivedLength = m_receivedLength;
|
|
|
| - // Prevent the XMLHttpRequest instance from being destoryed during
|
| - // |internalAbort()|.
|
| - RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
|
| -
|
| if (!internalAbort())
|
| return;
|
|
|
| @@ -1197,10 +1217,6 @@ void XMLHttpRequest::handleDidCancel()
|
| long long expectedLength = m_response.expectedContentLength();
|
| long long receivedLength = m_receivedLength;
|
|
|
| - // Prevent the XMLHttpRequest instance from being destoryed during
|
| - // |internalAbort()|.
|
| - RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
|
| -
|
| if (!internalAbort())
|
| return;
|
|
|
| @@ -1400,6 +1416,7 @@ String XMLHttpRequest::statusText() const
|
| void XMLHttpRequest::didFail(const ResourceError& error)
|
| {
|
| WTF_LOG(Network, "XMLHttpRequest %p didFail()", this);
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
|
|
| // If we are already in an error state, for instance we called abort(), bail out early.
|
| if (m_error)
|
| @@ -1428,6 +1445,7 @@ void XMLHttpRequest::didFail(const ResourceError& error)
|
| void XMLHttpRequest::didFailRedirectCheck()
|
| {
|
| WTF_LOG(Network, "XMLHttpRequest %p didFailRedirectCheck()", this);
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
|
|
| handleNetworkError();
|
| // Now the XMLHttpRequest instance may be dead.
|
| @@ -1436,6 +1454,7 @@ void XMLHttpRequest::didFailRedirectCheck()
|
| void XMLHttpRequest::didFinishLoading(unsigned long identifier, double)
|
| {
|
| WTF_LOG(Network, "XMLHttpRequest %p didFinishLoading(%lu)", this, identifier);
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
|
|
| if (m_error)
|
| return;
|
| @@ -1489,6 +1508,7 @@ void XMLHttpRequest::didFinishLoadingInternal()
|
| void XMLHttpRequest::didFinishLoadingFromBlob()
|
| {
|
| WTF_LOG(Network, "XMLHttpRequest %p didFinishLoadingFromBlob", this);
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
|
|
| didFinishLoadingInternal();
|
| }
|
| @@ -1496,6 +1516,7 @@ void XMLHttpRequest::didFinishLoadingFromBlob()
|
| void XMLHttpRequest::didFailLoadingFromBlob()
|
| {
|
| WTF_LOG(Network, "XMLHttpRequest %p didFailLoadingFromBlob()", this);
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
|
|
| if (m_error)
|
| return;
|
| @@ -1520,6 +1541,8 @@ PassRefPtr<BlobDataHandle> XMLHttpRequest::createBlobDataHandleFromResponse()
|
|
|
| void XMLHttpRequest::notifyParserStopped()
|
| {
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
| +
|
| // This should only be called when response document is parsed asynchronously.
|
| ASSERT(m_responseDocumentParser);
|
| ASSERT(!m_responseDocumentParser->isParsing());
|
| @@ -1556,6 +1579,7 @@ void XMLHttpRequest::endLoading()
|
| void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
|
| {
|
| WTF_LOG(Network, "XMLHttpRequest %p didSendData(%llu, %llu)", this, bytesSent, totalBytesToBeSent);
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
|
|
| if (!m_upload)
|
| return;
|
| @@ -1573,6 +1597,7 @@ void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long lon
|
| void XMLHttpRequest::didReceiveResponse(unsigned long identifier, const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle)
|
| {
|
| WTF_LOG(Network, "XMLHttpRequest %p didReceiveResponse(%lu)", this, identifier);
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
|
|
| m_response = response;
|
| if (!m_mimeTypeOverride.isEmpty()) {
|
| @@ -1590,9 +1615,6 @@ void XMLHttpRequest::didReceiveResponse(unsigned long identifier, const Resource
|
| m_responseStream = new ReadableStreamImpl<ReadableStreamChunkTypeTraits<DOMArrayBuffer>>(executionContext(), m_responseStreamSource);
|
| m_responseStreamSource->startStream(m_responseStream);
|
|
|
| - // This protection seems needed to keep |this| alive after changeState
|
| - // calling which may call event listeners.
|
| - RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
|
| changeState(HEADERS_RECEIVED);
|
| if (m_error) {
|
| // We need to check for |m_error| because |changeState| may trigger
|
| @@ -1649,6 +1671,7 @@ PassOwnPtr<TextResourceDecoder> XMLHttpRequest::createDecoder() const
|
|
|
| void XMLHttpRequest::didReceiveData(const char* data, unsigned len)
|
| {
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
| if (m_error)
|
| return;
|
|
|
| @@ -1703,6 +1726,7 @@ void XMLHttpRequest::didReceiveData(const char* data, unsigned len)
|
|
|
| void XMLHttpRequest::didDownloadData(int dataLength)
|
| {
|
| + ScopedEventDispatchProtect protect(&m_eventDispatchRecursionLevel);
|
| if (m_error)
|
| return;
|
|
|
| @@ -1732,10 +1756,6 @@ void XMLHttpRequest::handleDidTimeout()
|
| long long expectedLength = m_response.expectedContentLength();
|
| long long receivedLength = m_receivedLength;
|
|
|
| - // Prevent the XMLHttpRequest instance from being destoryed during
|
| - // |internalAbort()|.
|
| - RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
|
| -
|
| if (!internalAbort())
|
| return;
|
|
|
| @@ -1769,7 +1789,7 @@ bool XMLHttpRequest::hasPendingActivity() const
|
| return true;
|
| if (m_responseStream && m_responseStream->hasPendingActivity())
|
| return true;
|
| - return false;
|
| + return m_eventDispatchRecursionLevel > 0;
|
| }
|
|
|
| void XMLHttpRequest::contextDestroyed()
|
|
|