EventLoopInputDispatcher.cpp [plain text]
#include "config.h"
#include "EventLoopInputDispatcher.h"
#if ENABLE(WEB_REPLAY)
#include "Page.h"
#include "ReplayingInputCursor.h"
#include "WebReplayInputs.h"
#include <wtf/TemporaryChange.h>
#if !LOG_DISABLED
#include "Logging.h"
#include "SerializationMethods.h"
#include <replay/EncodedValue.h>
#include <wtf/text/CString.h>
#endif
namespace WebCore {
EventLoopInputDispatcher::EventLoopInputDispatcher(Page& page, ReplayingInputCursor& cursor, EventLoopInputDispatcherClient* client)
: m_page(page)
, m_client(client)
, m_cursor(cursor)
, m_timer(*this, &EventLoopInputDispatcher::timerFired)
, m_speed(DispatchSpeed::FastForward)
{
m_currentWork.input = nullptr;
m_currentWork.timestamp = 0.0;
}
void EventLoopInputDispatcher::run()
{
ASSERT(!m_running);
m_running = true;
LOG(WebReplay, "%-20s Starting dispatch of event loop inputs for page: %p\n", "ReplayEvents", &m_page);
dispatchInputSoon();
}
void EventLoopInputDispatcher::pause()
{
ASSERT(!m_dispatching);
ASSERT(m_running);
m_running = false;
LOG(WebReplay, "%-20s Pausing dispatch of event loop inputs for page: %p\n", "ReplayEvents", &m_page);
if (m_timer.isActive())
m_timer.stop();
}
void EventLoopInputDispatcher::timerFired()
{
dispatchInput();
}
void EventLoopInputDispatcher::dispatchInputSoon()
{
ASSERT(m_running);
if (!m_currentWork.input)
m_currentWork = m_cursor.loadEventLoopInput();
if (m_timer.isActive())
m_timer.stop();
double waitInterval = 0;
if (m_speed == DispatchSpeed::RealTime) {
if (!m_previousInputTimestamp)
m_previousInputTimestamp = m_currentWork.timestamp;
double targetInterval = m_currentWork.timestamp - m_previousInputTimestamp;
double elapsed = monotonicallyIncreasingTime() - m_previousDispatchStartTime;
waitInterval = targetInterval - elapsed;
}
if (waitInterval < 0)
waitInterval = 0;
if (waitInterval > 1000.0) {
LOG_ERROR("%-20s Tried to wait for over 1000 seconds before dispatching next event loop input; this is probably a bug.", "ReplayEvents");
waitInterval = 0;
}
LOG(WebReplay, "%-20s (WAIT: %.3f ms)", "ReplayEvents", waitInterval * 1000.0);
m_timer.startOneShot(waitInterval);
}
void EventLoopInputDispatcher::dispatchInput()
{
ASSERT(m_currentWork.input);
ASSERT(!m_dispatching);
if (m_speed == DispatchSpeed::RealTime) {
m_previousDispatchStartTime = monotonicallyIncreasingTime();
m_previousInputTimestamp = m_currentWork.timestamp;
}
#if !LOG_DISABLED
EncodedValue encodedInput = EncodingTraits<NondeterministicInputBase>::encodeValue(*m_currentWork.input);
String jsonString = encodedInput.asObject()->toJSONString();
LOG(WebReplay, "%-20s ----------------------------------------------", "ReplayEvents");
LOG(WebReplay, "%-20s >DISPATCH: %s %s\n", "ReplayEvents", m_currentWork.input->type().utf8().data(), jsonString.utf8().data());
#endif
m_client->willDispatchInput(*m_currentWork.input);
if (!m_running)
return;
{
TemporaryChange<bool> change(m_dispatching, true);
m_currentWork.input->dispatch(m_page.replayController());
}
EventLoopInputBase* dispatchedInput = m_currentWork.input;
m_currentWork.input = nullptr;
m_client->didDispatchInput(*dispatchedInput);
if (dispatchedInput->type() == InputTraits<EndSegmentSentinel>::type()) {
m_running = false;
m_dispatching = false;
m_client->didDispatchFinalInput();
return;
}
if (!m_running)
return;
dispatchInputSoon();
}
}
#endif // ENABLE(WEB_REPLAY)