Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(600)

Unified Diff: third_party/WebKit/Source/core/page/EventSource.cpp

Issue 1642563002: Introduce EventSourceParser (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@event-source-retry-fix
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/page/EventSource.cpp
diff --git a/third_party/WebKit/Source/core/page/EventSource.cpp b/third_party/WebKit/Source/core/page/EventSource.cpp
index 8b2231cb80c159fc92eafd520e9dc7df15411340..1995457e14725c796850ca482097a332f0a27b16 100644
--- a/third_party/WebKit/Source/core/page/EventSource.cpp
+++ b/third_party/WebKit/Source/core/page/EventSource.cpp
@@ -44,7 +44,6 @@
#include "core/frame/LocalDOMWindow.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/csp/ContentSecurityPolicy.h"
-#include "core/html/parser/TextResourceDecoder.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/loader/ThreadableLoader.h"
@@ -55,7 +54,6 @@
#include "platform/network/ResourceResponse.h"
#include "platform/weborigin/SecurityOrigin.h"
#include "public/platform/WebURLRequest.h"
-#include "wtf/ASCIICType.h"
#include "wtf/text/StringBuilder.h"
namespace blink {
@@ -67,9 +65,7 @@ inline EventSource::EventSource(ExecutionContext* context, const KURL& url, cons
, m_url(url)
, m_withCredentials(eventSourceInit.withCredentials())
, m_state(CONNECTING)
- , m_decoder(TextResourceDecoder::create("text/plain", "UTF-8"))
, m_connectTimer(this, &EventSource::connectTimerFired)
- , m_discardTrailingNewline(false)
, m_requestInFlight(false)
, m_reconnectDelay(defaultReconnectDelay)
{
@@ -128,10 +124,10 @@ void EventSource::connect()
request.setHTTPHeaderField(HTTPNames::Accept, "text/event-stream");
request.setHTTPHeaderField(HTTPNames::Cache_Control, "no-cache");
request.setRequestContext(WebURLRequest::RequestContextEventSource);
- if (!m_lastEventId.isEmpty()) {
+ if (m_parser && !m_parser->lastEventId().isEmpty()) {
// HTTP headers are Latin-1 byte strings, but the Last-Event-ID header is encoded as UTF-8.
// TODO(davidben): This should be captured in the type of setHTTPHeaderField's arguments.
- CString lastEventIdUtf8 = m_lastEventId.utf8();
+ CString lastEventIdUtf8 = m_parser->lastEventId().utf8();
request.setHTTPHeaderField(HTTPNames::Last_Event_ID, AtomicString(reinterpret_cast<const LChar*>(lastEventIdUtf8.data()), lastEventIdUtf8.length()));
Tom Sepez 2016/02/12 17:14:30 So if this is untrusted, do we need to verfiy that
yhirano 2016/02/12 21:33:27 It cannot contain CR or LF, but it can contain oth
}
@@ -202,6 +198,8 @@ void EventSource::close()
ASSERT(!m_requestInFlight);
return;
}
+ if (m_parser)
+ m_parser->stop();
// Stop trying to reconnect if EventSource was explicitly closed or if ActiveDOMObject::stop() was called.
if (m_connectTimer.isActive()) {
@@ -260,6 +258,12 @@ void EventSource::didReceiveResponse(unsigned long, const ResourceResponse& resp
if (responseIsValid) {
m_state = OPEN;
+ AtomicString lastEventId;
+ if (m_parser) {
+ // The new parser takes over the event ID.
+ lastEventId = m_parser->lastEventId();
+ }
+ m_parser = new EventSourceParser(lastEventId, this);
dispatchEvent(Event::create(EventTypeNames::open));
} else {
m_loader->cancel();
@@ -271,9 +275,9 @@ void EventSource::didReceiveData(const char* data, unsigned length)
{
ASSERT(m_state == OPEN);
ASSERT(m_requestInFlight);
+ ASSERT(m_parser);
- append(m_receiveBuf, m_decoder->decode(data, length));
- parseEventStream();
+ m_parser->addBytes(data, length);
}
void EventSource::didFinishLoading(unsigned long, double)
@@ -281,15 +285,6 @@ void EventSource::didFinishLoading(unsigned long, double)
ASSERT(m_state == OPEN);
ASSERT(m_requestInFlight);
- if (m_receiveBuf.size() > 0 || m_data.size() > 0) {
- parseEventStream();
-
- // Discard everything that has not been dispatched by now.
- m_receiveBuf.clear();
- m_data.clear();
- m_eventName = emptyAtom;
- m_currentlyParsedEventId = nullAtom;
- }
networkRequestEnded();
}
@@ -316,6 +311,20 @@ void EventSource::didFailRedirectCheck()
abortConnectionAttempt();
}
+void EventSource::onMessageEvent(const AtomicString& eventType, const String& data, const AtomicString& lastEventId)
+{
+ RefPtrWillBeRawPtr<MessageEvent> e = MessageEvent::create();
+ e->initMessageEvent(eventType, false, false, SerializedScriptValueFactory::instance().create(data), m_eventStreamOrigin, lastEventId, 0, nullptr);
+
+ InspectorInstrumentation::willDispatchEventSourceEvent(executionContext(), this, eventType, lastEventId, data);
+ dispatchEvent(e);
+}
+
+void EventSource::onReconnectionTimeSet(unsigned long long reconnectionTime)
+{
+ m_reconnectDelay = reconnectionTime;
+}
+
void EventSource::abortConnectionAttempt()
{
ASSERT(m_state == CONNECTING);
@@ -327,105 +336,6 @@ void EventSource::abortConnectionAttempt()
dispatchEvent(Event::create(EventTypeNames::error));
}
-void EventSource::parseEventStream()
-{
- unsigned bufPos = 0;
- unsigned bufSize = m_receiveBuf.size();
- while (bufPos < bufSize) {
- if (m_discardTrailingNewline) {
- if (m_receiveBuf[bufPos] == '\n')
- bufPos++;
- m_discardTrailingNewline = false;
- }
-
- int lineLength = -1;
- int fieldLength = -1;
- for (unsigned i = bufPos; lineLength < 0 && i < bufSize; i++) {
- switch (m_receiveBuf[i]) {
- case ':':
- if (fieldLength < 0)
- fieldLength = i - bufPos;
- break;
- case '\r':
- m_discardTrailingNewline = true;
- case '\n':
- lineLength = i - bufPos;
- break;
- }
- }
-
- if (lineLength < 0)
- break;
-
- parseEventStreamLine(bufPos, fieldLength, lineLength);
- bufPos += lineLength + 1;
-
- // EventSource.close() might've been called by one of the message event handlers.
- // Per spec, no further messages should be fired after that.
- if (m_state == CLOSED)
- break;
- }
-
- if (bufPos == bufSize)
- m_receiveBuf.clear();
- else if (bufPos)
- m_receiveBuf.remove(0, bufPos);
-}
-
-void EventSource::parseEventStreamLine(unsigned bufPos, int fieldLength, int lineLength)
-{
- if (!lineLength) {
- if (!m_data.isEmpty()) {
- m_data.removeLast();
- if (!m_currentlyParsedEventId.isNull()) {
- m_lastEventId = m_currentlyParsedEventId;
- m_currentlyParsedEventId = nullAtom;
- }
- InspectorInstrumentation::willDispachEventSourceEvent(executionContext(), this, m_eventName.isEmpty() ? EventTypeNames::message : m_eventName, m_lastEventId, m_data);
- dispatchEvent(createMessageEvent());
- }
- if (!m_eventName.isEmpty())
- m_eventName = emptyAtom;
- } else if (fieldLength) {
- bool noValue = fieldLength < 0;
-
- String field(&m_receiveBuf[bufPos], noValue ? lineLength : fieldLength);
- int step;
- if (noValue)
- step = lineLength;
- else if (m_receiveBuf[bufPos + fieldLength + 1] != ' ')
- step = fieldLength + 1;
- else
- step = fieldLength + 2;
- bufPos += step;
- int valueLength = lineLength - step;
-
- if (field == "data") {
- if (valueLength)
- m_data.append(&m_receiveBuf[bufPos], valueLength);
- m_data.append('\n');
- } else if (field == "event") {
- m_eventName = valueLength ? AtomicString(&m_receiveBuf[bufPos], valueLength) : "";
- } else if (field == "id") {
- m_currentlyParsedEventId = valueLength ? AtomicString(&m_receiveBuf[bufPos], valueLength) : "";
- } else if (field == "retry") {
- bool hasOnlyDigits = true;
- for (int i = 0; i < valueLength && hasOnlyDigits; ++i) {
- hasOnlyDigits = isASCIIDigit(m_receiveBuf[bufPos + i]);
- }
- if (!valueLength) {
- m_reconnectDelay = defaultReconnectDelay;
- } else if (hasOnlyDigits) {
- String value(&m_receiveBuf[bufPos], valueLength);
- bool ok;
- unsigned long long retry = value.toUInt64(&ok);
- if (ok)
- m_reconnectDelay = retry;
- }
- }
- }
-}
-
void EventSource::stop()
{
close();
@@ -443,18 +353,12 @@ bool EventSource::hasPendingActivity() const
return m_state != CLOSED;
}
-PassRefPtrWillBeRawPtr<MessageEvent> EventSource::createMessageEvent()
-{
- RefPtrWillBeRawPtr<MessageEvent> event = MessageEvent::create();
- event->initMessageEvent(m_eventName.isEmpty() ? EventTypeNames::message : m_eventName, false, false, SerializedScriptValueFactory::instance().create(String(m_data)), m_eventStreamOrigin, m_lastEventId, 0, nullptr);
- m_data.clear();
- return event.release();
-}
-
DEFINE_TRACE(EventSource)
{
+ visitor->trace(m_parser);
RefCountedGarbageCollectedEventTargetWithInlineData::trace(visitor);
ActiveDOMObject::trace(visitor);
+ EventSourceParser::Client::trace(visitor);
}
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698