Index: Source/core/xml/XMLHttpRequest.cpp |
diff --git a/Source/core/xml/XMLHttpRequest.cpp b/Source/core/xml/XMLHttpRequest.cpp |
index 3e6bf6c9ed6e875d727eb210fdd20f233c178433..b3cc69b82597c52b7dde232f35a5fdf020f82482 100644 |
--- a/Source/core/xml/XMLHttpRequest.cpp |
+++ b/Source/core/xml/XMLHttpRequest.cpp |
@@ -58,12 +58,23 @@ |
#include "wtf/ArrayBuffer.h" |
#include "wtf/ArrayBufferView.h" |
#include "wtf/Assertions.h" |
+#include "wtf/CurrentTime.h" |
#include "wtf/RefCountedLeakCounter.h" |
#include "wtf/StdLibExtras.h" |
#include "wtf/text/CString.h" |
namespace blink { |
+// To throttle readystatechange event fired when readystatechange is not |
+// changed, we don't dispatch the event within 50ms. |
+// As dispatching readystatechange when readystatechange is NOT changed is not |
+// specified, 50ms is not specified, too. |
+// We choose this value because progress event is dispatched every 50ms, but |
+// actually this value doesn't have to equal to the interval. |
+// Note: When readystate is actually changed readystatechange event must be |
+// dispatched no matter how recently dispatched the event was. |
+const double readyStateChangeFireInterval = 0.05; |
+ |
DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XMLHttpRequest")); |
struct XMLHttpRequestStaticData { |
@@ -169,6 +180,7 @@ XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOri |
, m_progressEventThrottle(this) |
, m_responseTypeCode(ResponseTypeDefault) |
, m_securityOrigin(securityOrigin) |
+ , m_previousReadyStateChangeFireTime(0) |
, m_async(true) |
, m_includeCredentials(false) |
, m_createdDocument(false) |
@@ -420,12 +432,15 @@ void XMLHttpRequest::trackProgress(int length) |
if (m_state != LOADING) { |
changeState(LOADING); |
} else { |
- // Firefox calls readyStateChanged every time it receives data. Do |
- // the same to align with Firefox. |
- // |
- // FIXME: Make our implementation and the spec consistent. This |
- // behavior was needed when the progress event was not available. |
- dispatchReadyStateChangeEvent(); |
+ // FIXME: Make our implementation and the spec consistent. This extra |
+ // invocation of readystatechange event in LOADING state was needed |
+ // when the progress event was not available. |
+ double now = monotonicallyIncreasingTime(); |
+ bool shouldFire = now - m_previousReadyStateChangeFireTime >= readyStateChangeFireInterval; |
+ if (shouldFire) { |
+ m_previousReadyStateChangeFireTime = now; |
+ dispatchReadyStateChangeEvent(); |
+ } |
} |
} |