Index: Source/core/xml/XMLHttpRequest.cpp |
diff --git a/Source/core/xml/XMLHttpRequest.cpp b/Source/core/xml/XMLHttpRequest.cpp |
index 2af04637525e5de865aba366a12bc99b3cb2dbd4..777ed7d2b71471cc95d93394c6314cd220d04fd4 100644 |
--- a/Source/core/xml/XMLHttpRequest.cpp |
+++ b/Source/core/xml/XMLHttpRequest.cpp |
@@ -441,9 +441,9 @@ void XMLHttpRequest::dispatchReadyStateChangeEvent() |
InspectorInstrumentation::didDispatchXHRReadyStateChangeEvent(cookie); |
if (m_state == DONE && !m_error) { |
InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRLoadEvent(executionContext(), this); |
- m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(EventTypeNames::load)); |
+ dispatchThrottledProgressEventSnapshot(EventTypeNames::load); |
InspectorInstrumentation::didDispatchXHRLoadEvent(cookie); |
- m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(EventTypeNames::loadend)); |
+ dispatchThrottledProgressEventSnapshot(EventTypeNames::loadend); |
} |
} |
@@ -856,6 +856,10 @@ void XMLHttpRequest::abort() |
bool sendFlag = m_loader; |
+ // Response is cleared next, save needed progress event data. |
+ long long expectedLength = m_response.expectedContentLength(); |
+ long long receivedLength = m_receivedLength; |
+ |
if (!internalAbort()) |
return; |
@@ -866,7 +870,7 @@ void XMLHttpRequest::abort() |
if (!((m_state <= OPENED && !sendFlag) || m_state == DONE)) { |
ASSERT(!m_loader); |
- handleRequestError(0, EventTypeNames::abort); |
+ handleRequestError(0, EventTypeNames::abort, receivedLength, expectedLength); |
} |
m_state = UNSENT; |
} |
@@ -958,31 +962,42 @@ void XMLHttpRequest::handleDidFailGeneric() |
m_error = true; |
} |
-void XMLHttpRequest::dispatchEventAndLoadEnd(const AtomicString& type) |
+void XMLHttpRequest::dispatchEventAndLoadEnd(const AtomicString& type, long long receivedLength, long long expectedLength) |
{ |
- if (!m_uploadComplete) { |
- m_uploadComplete = true; |
- if (m_upload && m_uploadEventsAllowed) |
- m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(type)); |
- } |
- m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(type)); |
+ bool lengthComputable = expectedLength > 0 && receivedLength <= expectedLength; |
+ unsigned long long loaded = receivedLength >= 0 ? static_cast<unsigned long long>(receivedLength) : 0; |
+ unsigned long long total = lengthComputable ? static_cast<unsigned long long>(expectedLength) : 0; |
+ |
+ m_progressEventThrottle.dispatchEventAndLoadEnd(type, lengthComputable, loaded, total); |
} |
-void XMLHttpRequest::dispatchThrottledProgressEvent() |
+void XMLHttpRequest::dispatchThrottledProgressEvent(const AtomicString& type, long long receivedLength, long long expectedLength) |
{ |
- long long expectedLength = m_response.expectedContentLength(); |
- bool lengthComputable = expectedLength > 0 && m_receivedLength <= expectedLength; |
- unsigned long long total = lengthComputable ? expectedLength : 0; |
+ bool lengthComputable = expectedLength > 0 && receivedLength <= expectedLength; |
+ unsigned long long loaded = receivedLength >= 0 ? static_cast<unsigned long long>(receivedLength) : 0; |
+ unsigned long long total = lengthComputable ? static_cast<unsigned long long>(expectedLength) : 0; |
+ |
+ if (type == EventTypeNames::progress) |
+ m_progressEventThrottle.dispatchProgressEvent(lengthComputable, loaded, total); |
+ else |
+ m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::create(type, lengthComputable, loaded, total)); |
+} |
- m_progressEventThrottle.dispatchProgressEvent(lengthComputable, m_receivedLength, total); |
+void XMLHttpRequest::dispatchThrottledProgressEventSnapshot(const AtomicString& type) |
+{ |
+ return dispatchThrottledProgressEvent(type, m_receivedLength, m_response.expectedContentLength()); |
} |
void XMLHttpRequest::handleNetworkError() |
{ |
LOG(Network, "XMLHttpRequest %p handleNetworkError()", this); |
+ // Response is cleared next, save needed progress event data. |
+ long long expectedLength = m_response.expectedContentLength(); |
+ long long receivedLength = m_receivedLength; |
+ |
handleDidFailGeneric(); |
- handleRequestError(NetworkError, EventTypeNames::error); |
+ handleRequestError(NetworkError, EventTypeNames::error, receivedLength, expectedLength); |
internalAbort(); |
} |
@@ -990,11 +1005,15 @@ void XMLHttpRequest::handleDidCancel() |
{ |
LOG(Network, "XMLHttpRequest %p handleDidCancel()", this); |
+ // Response is cleared next, save needed progress event data. |
+ long long expectedLength = m_response.expectedContentLength(); |
+ long long receivedLength = m_receivedLength; |
+ |
handleDidFailGeneric(); |
- handleRequestError(AbortError, EventTypeNames::abort); |
+ handleRequestError(AbortError, EventTypeNames::abort, receivedLength, expectedLength); |
} |
-void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode, const AtomicString& type) |
+void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode, const AtomicString& type, long long receivedLength, long long expectedLength) |
{ |
LOG(Network, "XMLHttpRequest %p handleRequestError()", this); |
@@ -1018,8 +1037,8 @@ void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode, const Atomi |
m_upload->handleRequestError(type); |
} |
- dispatchThrottledProgressEvent(); |
- m_progressEventThrottle.dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(type)); |
+ dispatchThrottledProgressEvent(EventTypeNames::progress, receivedLength, expectedLength); |
+ dispatchEventAndLoadEnd(type, receivedLength, expectedLength); |
} |
void XMLHttpRequest::dropProtectionSoon() |
@@ -1219,8 +1238,6 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier, double) |
if (m_decoder) |
m_responseText = m_responseText.concatenateWith(m_decoder->flush()); |
- clearVariablesForLoading(); |
- |
if (m_responseStream) |
m_responseStream->finalize(); |
@@ -1235,6 +1252,8 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier, double) |
} |
changeState(DONE); |
+ |
+ clearVariablesForLoading(); |
} |
void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent) |
@@ -1250,7 +1269,7 @@ void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long lon |
if (bytesSent == totalBytesToBeSent && !m_uploadComplete) { |
m_uploadComplete = true; |
if (m_uploadEventsAllowed) |
- m_upload->dispatchEventAndLoadEnd(XMLHttpRequestProgressEvent::create(EventTypeNames::load)); |
+ m_upload->dispatchEventAndLoadEnd(EventTypeNames::load, true, bytesSent, totalBytesToBeSent); |
} |
} |
@@ -1321,7 +1340,7 @@ void XMLHttpRequest::didReceiveData(const char* data, int len) |
m_receivedLength += len; |
if (m_async) |
- dispatchThrottledProgressEvent(); |
+ dispatchThrottledProgressEventSnapshot(EventTypeNames::progress); |
if (m_state != LOADING) { |
changeState(LOADING); |
@@ -1342,11 +1361,15 @@ void XMLHttpRequest::handleDidTimeout() |
// internalAbort() calls dropProtection(), which may release the last reference. |
RefPtr<XMLHttpRequest> protect(this); |
+ // Response is cleared next, save needed progress event data. |
+ long long expectedLength = m_response.expectedContentLength(); |
+ long long receivedLength = m_receivedLength; |
+ |
if (!internalAbort()) |
return; |
handleDidFailGeneric(); |
- handleRequestError(TimeoutError, EventTypeNames::timeout); |
+ handleRequestError(TimeoutError, EventTypeNames::timeout, receivedLength, expectedLength); |
} |
void XMLHttpRequest::suspend() |