XMLHttpRequestProgressEventThrottle.cpp [plain text]
#include "config.h"
#include "XMLHttpRequestProgressEventThrottle.h"
#include "EventNames.h"
#include "EventTarget.h"
#include "XMLHttpRequestProgressEvent.h"
namespace WebCore {
const double XMLHttpRequestProgressEventThrottle::minimumProgressEventDispatchingIntervalInSeconds = .05;
XMLHttpRequestProgressEventThrottle::XMLHttpRequestProgressEventThrottle(EventTarget* target)
: m_target(target)
, m_hasThrottledProgressEvent(false)
, m_lengthComputable(false)
, m_loaded(0)
, m_total(0)
, m_deferEvents(false)
, m_dispatchDeferredEventsTimer(*this, &XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents)
{
ASSERT(target);
}
XMLHttpRequestProgressEventThrottle::~XMLHttpRequestProgressEventThrottle()
{
}
void XMLHttpRequestProgressEventThrottle::dispatchThrottledProgressEvent(bool lengthComputable, unsigned long long loaded, unsigned long long total)
{
m_lengthComputable = lengthComputable;
m_loaded = loaded;
m_total = total;
if (!m_target->hasEventListeners(eventNames().progressEvent))
return;
if (m_deferEvents) {
m_deferredProgressEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total);
return;
}
if (!isActive()) {
ASSERT(!m_hasThrottledProgressEvent);
dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, lengthComputable, loaded, total));
startRepeating(minimumProgressEventDispatchingIntervalInSeconds);
m_hasThrottledProgressEvent = false;
return;
}
m_hasThrottledProgressEvent = true;
}
void XMLHttpRequestProgressEventThrottle::dispatchReadyStateChangeEvent(Event& event, ProgressEventAction progressEventAction)
{
if (progressEventAction == FlushProgressEvent)
flushProgressEvent();
dispatchEvent(event);
}
void XMLHttpRequestProgressEventThrottle::dispatchEvent(Event& event)
{
if (m_deferEvents) {
if (m_deferredEvents.size() > 1 && event.type() == eventNames().readystatechangeEvent && event.type() == m_deferredEvents.last()->type()) {
return;
}
m_deferredEvents.append(event);
} else
m_target->dispatchEvent(event);
}
void XMLHttpRequestProgressEventThrottle::dispatchProgressEvent(const AtomicString& type)
{
ASSERT(type == eventNames().loadstartEvent || type == eventNames().progressEvent || type == eventNames().loadEvent || type == eventNames().loadendEvent || type == eventNames().abortEvent || type == eventNames().errorEvent || type == eventNames().timeoutEvent);
if (type == eventNames().loadstartEvent) {
m_lengthComputable = false;
m_loaded = 0;
m_total = 0;
}
if (m_target->hasEventListeners(type))
dispatchEvent(XMLHttpRequestProgressEvent::create(type, m_lengthComputable, m_loaded, m_total));
}
void XMLHttpRequestProgressEventThrottle::flushProgressEvent()
{
if (m_deferEvents && m_deferredProgressEvent) {
m_deferredEvents.append(m_deferredProgressEvent.releaseNonNull());
return;
}
if (!hasEventToDispatch())
return;
Ref<Event> event = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
m_hasThrottledProgressEvent = false;
stop();
dispatchEvent(WTFMove(event));
}
void XMLHttpRequestProgressEventThrottle::dispatchDeferredEvents()
{
ASSERT(m_deferEvents);
m_deferEvents = false;
auto deferredEvents = WTFMove(m_deferredEvents);
RefPtr<Event> deferredProgressEvent = WTFMove(m_deferredProgressEvent);
for (auto& deferredEvent : deferredEvents)
dispatchEvent(deferredEvent);
if (deferredProgressEvent)
dispatchEvent(*deferredProgressEvent);
}
void XMLHttpRequestProgressEventThrottle::fired()
{
ASSERT(isActive());
if (!hasEventToDispatch()) {
stop();
return;
}
dispatchEvent(XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total));
m_hasThrottledProgressEvent = false;
}
bool XMLHttpRequestProgressEventThrottle::hasEventToDispatch() const
{
return m_hasThrottledProgressEvent && isActive();
}
void XMLHttpRequestProgressEventThrottle::suspend()
{
if (m_dispatchDeferredEventsTimer.isActive()) {
ASSERT(m_deferEvents);
m_dispatchDeferredEventsTimer.stop();
return;
}
ASSERT(!m_deferredProgressEvent);
ASSERT(m_deferredEvents.isEmpty());
ASSERT(!m_deferEvents);
m_deferEvents = true;
if (hasEventToDispatch()) {
m_deferredProgressEvent = XMLHttpRequestProgressEvent::create(eventNames().progressEvent, m_lengthComputable, m_loaded, m_total);
m_hasThrottledProgressEvent = false;
}
stop();
}
void XMLHttpRequestProgressEventThrottle::resume()
{
ASSERT(!m_hasThrottledProgressEvent);
if (m_deferredEvents.isEmpty() && !m_deferredProgressEvent) {
m_deferEvents = false;
return;
}
m_dispatchDeferredEventsTimer.startOneShot(0);
}
}