Bug 710546 - Server sent events Once the end of the file is reached, any pending data must be discarde, r=smaug
authorwfernandom2004@gmail.com
Tue, 22 Jan 2013 21:09:13 +0200
changeset 129344 653199a8edea98b0eb8c6ec7c58c19260e3884cb
parent 129343 70daa2f8de6a24c186fadf7fae3da73c696e3493
child 129345 2876e73c9b6fa152ab8da2542adb4db678c13113
push id2323
push userbbajaj@mozilla.com
push dateMon, 01 Apr 2013 19:47:02 +0000
treeherdermozilla-beta@7712be144d91 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs710546
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 710546 - Server sent events Once the end of the file is reached, any pending data must be discarde, r=smaug
content/base/src/EventSource.cpp
content/base/test/Makefile.in
content/base/test/accesscontrol.resource
content/base/test/badContentType.eventsource
content/base/test/badEventFieldName.eventsource
content/base/test/badEventFieldName.eventsource^headers^
content/base/test/badHTTPResponseCode.eventsource
content/base/test/badMessageEvent.eventsource
content/base/test/badMessageEvent2.eventsource
content/base/test/badMessageEvent2.eventsource^headers^
content/base/test/delayedServerEvents.sjs
content/base/test/eventsource.resource
content/base/test/eventsource_redirect_to.resource
content/base/test/forRemoval.resource
content/base/test/invalid_accesscontrol.resource
content/base/test/somedatas.resource
content/base/test/test_bug338583.html
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -449,48 +449,24 @@ EventSource::OnStopRequest(nsIRequest *a
 
   if (NS_FAILED(aStatusCode)) {
     DispatchFailConnection();
     return aStatusCode;
   }
 
   nsresult rv;
   nsresult healthOfRequestResult = CheckHealthOfRequestCallback(aRequest);
-  if (NS_SUCCEEDED(healthOfRequestResult)) {
-    // check if we had an incomplete UTF8 char at the end of the stream
-    if (mLastConvertionResult == NS_PARTIAL_MORE_INPUT) {
-      rv = ParseCharacter(REPLACEMENT_CHAR);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
+  if (NS_SUCCEEDED(healthOfRequestResult) &&
+      mLastConvertionResult == NS_PARTIAL_MORE_INPUT) {
+    // we had an incomplete UTF8 char at the end of the stream
+    rv = ParseCharacter(REPLACEMENT_CHAR);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
 
-    // once we reach the end of the stream we must
-    // dispatch the current event
-    switch (mStatus)
-    {
-      case PARSE_STATE_CR_CHAR:
-      case PARSE_STATE_COMMENT:
-      case PARSE_STATE_FIELD_NAME:
-      case PARSE_STATE_FIRST_CHAR_OF_FIELD_VALUE:
-      case PARSE_STATE_FIELD_VALUE:
-      case PARSE_STATE_BEGIN_OF_LINE:
-        rv = SetFieldAndClear();
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        rv = DispatchCurrentMessageEvent();  // there is an empty line (CRCR)
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        break;
-
-      // Just for not getting warnings when compiling
-      case PARSE_STATE_OFF:
-      case PARSE_STATE_BEGIN_OF_STREAM:
-      case PARSE_STATE_BOM_WAS_READ:
-        break;
-    }
-  }
+  ClearFields();
 
   nsCOMPtr<nsIRunnable> event =
     NS_NewRunnableMethod(this, &EventSource::ReestablishConnection);
   NS_ENSURE_STATE(event);
 
   rv = NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -1293,16 +1269,18 @@ EventSource::DispatchAllMessageEvents()
 
     messageEvent->SetTrusted(true);
 
     rv = DispatchDOMEvent(nullptr, event, nullptr, nullptr);
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to dispatch the message event!!!");
       return;
     }
+
+    mLastEventID.Assign(message->mLastEventID);
   }
 }
 
 nsresult
 EventSource::ClearFields()
 {
   // mLastEventID and mReconnectionTime must be cached
 
@@ -1343,17 +1321,16 @@ EventSource::SetFieldAndClear()
       if (mLastFieldName.EqualsLiteral("event")) {
         mCurrentMessage.mEventName.Assign(mLastFieldValue);
       }
       break;
 
     case PRUnichar('i'):
       if (mLastFieldName.EqualsLiteral("id")) {
         mCurrentMessage.mLastEventID.Assign(mLastFieldValue);
-        mLastEventID.Assign(mLastFieldValue);
       }
       break;
 
     case PRUnichar('r'):
       if (mLastFieldName.EqualsLiteral("retry")) {
         uint32_t newValue=0;
         uint32_t i = 0;  // we must ensure that there are only digits
         bool assign = true;
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -492,18 +492,16 @@ MOCHITEST_FILES_B = \
 		eventsource.resource \
 		eventsource.resource^headers^ \
 		eventsource_redirect.resource \
 		eventsource_redirect.resource^headers^ \
 		eventsource_redirect_to.resource \
 		eventsource_redirect_to.resource^headers^ \
 		badContentType.eventsource \
 		badContentType.eventsource^headers^ \
-		badEventFieldName.eventsource \
-		badEventFieldName.eventsource^headers^ \
 		badHTTPResponseCode.eventsource \
 		badHTTPResponseCode.eventsource^headers^ \
 		badMessageEvent.eventsource \
 		badMessageEvent.eventsource^headers^ \
 		file_restrictedEventSource.sjs \
 		forRemoval.resource \
 		forRemoval.resource^headers^ \
 		accesscontrol.resource \
@@ -622,16 +620,18 @@ MOCHITEST_FILES_B = \
 		test_textnode_normalize_in_selection.html \
 		test_xhr_send_readystate.html \
 		test_bug813919.html \
 		test_bug814576.html \
 		test_xhr_withCredentials.html \
 		test_bothCSPheaders.html \
 		file_bothCSPheaders.html \
 		file_bothCSPheaders.html^headers^ \
+		badMessageEvent2.eventsource \
+		badMessageEvent2.eventsource^headers^ \
 		$(NULL)
 
 # OOP tests don't work on Windows (bug 763081) or native-fennec
 # (see Bug 774939)
 ifneq ($(OS_ARCH),WINNT)
 ifndef MOZ_ANDROID_OMTC
 MOCHITEST_FILES_B += \
 		test_messagemanager_assertpermission.html \
--- a/content/base/test/accesscontrol.resource
+++ b/content/base/test/accesscontrol.resource
@@ -1,5 +1,7 @@
 :this file must be enconded in utf8
 :and its Content-Type must be equal to text/event-stream
 
 event: message
-data: 1
\ No newline at end of file
+data: 1
+
+
--- a/content/base/test/badContentType.eventsource
+++ b/content/base/test/badContentType.eventsource
@@ -1,3 +1,5 @@
 retry:500
 event: message
 data: 1
+
+
deleted file mode 100644
--- a/content/base/test/badEventFieldName.eventsource
+++ /dev/null
@@ -1,4 +0,0 @@
-retry:500
-:space isn't a valid NCName char, am I right?
-event: message event
-data: 1
deleted file mode 100644
--- a/content/base/test/badEventFieldName.eventsource^headers^
+++ /dev/null
@@ -1,1 +0,0 @@
-Content-Type: text/event-stream
--- a/content/base/test/badHTTPResponseCode.eventsource
+++ b/content/base/test/badHTTPResponseCode.eventsource
@@ -1,3 +1,5 @@
 retry:500
 event: message
 data: 1
+
+
--- a/content/base/test/badMessageEvent.eventsource
+++ b/content/base/test/badMessageEvent.eventsource
@@ -1,2 +1,4 @@
 retry:500
 event: message
+
+
new file mode 100644
--- /dev/null
+++ b/content/base/test/badMessageEvent2.eventsource
@@ -0,0 +1,5 @@
+retry:500
+data: ok
+
+id: invalid-id
+data: not-ok
new file mode 100644
--- /dev/null
+++ b/content/base/test/badMessageEvent2.eventsource^headers^
@@ -0,0 +1,1 @@
+Content-Type: text/event-stream
--- a/content/base/test/delayedServerEvents.sjs
+++ b/content/base/test/delayedServerEvents.sjs
@@ -1,15 +1,15 @@
 // this will take strings_to_send.length*500 ms = 5 sec
 
 var timer = null;
 var strings_to_send = ["data\r\n\nda", "ta", ":", "de", "layed1\n\n",
                        "",
                        "",
-                       "data:delayed2", "", ""];
+                       "data:delayed2\n\n", "", ""];
 var resp = null;
 
 function sendNextString()
 {
   if (strings_to_send.length == 0) {
     timer.cancel();
     resp.finish();
     timer = null;
--- a/content/base/test/eventsource.resource
+++ b/content/base/test/eventsource.resource
@@ -13,8 +13,10 @@ unknow: unknow
 event: click
 retry:500
 
 event: blur
 retry:500
 
 event:keypress
 retry:500
+
+
--- a/content/base/test/eventsource_redirect_to.resource
+++ b/content/base/test/eventsource_redirect_to.resource
@@ -1,3 +1,4 @@
 retry:500
 data: 1
 
+
--- a/content/base/test/forRemoval.resource
+++ b/content/base/test/forRemoval.resource
@@ -16,8 +16,9 @@ data: 3
 retry:500
 event: message
 data: 4
 
 retry:500
 event: message
 data: 5
 
+
--- a/content/base/test/invalid_accesscontrol.resource
+++ b/content/base/test/invalid_accesscontrol.resource
@@ -1,5 +1,7 @@
 :this file must be enconded in utf8
 :and its Content-Type must be equal to text/event-stream
 
 event: message
-data: 1
\ No newline at end of file
+data: 1
+
+
--- a/content/base/test/somedatas.resource
+++ b/content/base/test/somedatas.resource
@@ -8,10 +8,9 @@ data:12345678912345678912345678912345678
 data:  123456789123456789123456789123456789123456789123456789123456789123456789
 :some utf-8 characteres
 data:çãá"'@`~Ý Ḿyyyy
 
 :test if the character ":"(which is used for comments) isn't misunderstood
 data:  :xxabcdefghij
 data:çãá"'@`~Ý Ḿyyyy : zz
 
-:a message dispatched because of eof
-data:1
+
--- a/content/base/test/test_bug338583.html
+++ b/content/base/test/test_bug338583.html
@@ -202,18 +202,18 @@ https://bugzilla.mozilla.org/show_bug.cg
 
 // in order to test (3)
 //   a) XSite domain error test
 //   b) protocol file:// test
 //   c) protocol javascript: test
 //   d) wrong Content-Type test
 //   e) bad http response code test
 //   f) message eventsource without a data test
-//   g) eventsource with invalid NCName char in the event field test
-//   h) DNS error
+//   g) DNS error
+//   h) EventSource which last message doesn't end with an empty line. See bug 710546
 
   function doTest3(test_id) {
     gEventSourceObj3_a = new EventSource("http://example.org/tests/content/base/test/eventsource.resource");
 
     gEventSourceObj3_a.onmessage = fn_onmessage;
     gEventSourceObj3_a.hits = [];
     gEventSourceObj3_a.hits['fn_onmessage'] = 0;
 
@@ -305,40 +305,54 @@ https://bugzilla.mozilla.org/show_bug.cg
     }, parseInt(1500*stress_factor));
   }
 
   function fnInvalidNCName() {
     fnInvalidNCName.hits++;
   }
 
   function doTest3_g(test_id) {
-    gEventSourceObj3_g = new EventSource("badEventFieldName.eventsource");
+    gEventSourceObj3_g = new EventSource("http://hdfskjghsbg.jtiyoejowe.dafsgbhjab.com");
 
-    fnInvalidNCName.hits = 0;
-    gEventSourceObj3_g.addEventListener('message event', fnInvalidNCName, true);
+    gEventSourceObj3_g.onmessage = fn_onmessage;
+    gEventSourceObj3_g.hits = [];
+    gEventSourceObj3_g.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
-      ok(fnInvalidNCName.hits != 0, "Test 3.g failed");
+      ok(gEventSourceObj3_g.hits['fn_onmessage'] == 0, "Test 3.g failed");
       gEventSourceObj3_g.close();
       setTestHasFinished(test_id);
     }, parseInt(1500*stress_factor));
   }
 
+  function fnMessageListenerTest3h(e) {
+    fnMessageListenerTest3h.msg_ok = (fnMessageListenerTest3h.msg_ok && e.data == "ok");
+    fnMessageListenerTest3h.id_ok = (fnMessageListenerTest3h.msg_ok && e.lastEventId == "");
+  }
+
   function doTest3_h(test_id) {
-    gEventSourceObj3_h = new EventSource("http://hdfskjghsbg.jtiyoejowe.dafsgbhjab.com");
+    gEventSourceObj3_h = new EventSource("badMessageEvent2.eventsource");
+
+    gEventSourceObj3_h.addEventListener('message event', fnMessageListenerTest3h, true);
+    fnMessageListenerTest3h.msg_ok = true;
+    fnMessageListenerTest3h.id_ok = true;
 
     gEventSourceObj3_h.onmessage = fn_onmessage;
     gEventSourceObj3_h.hits = [];
     gEventSourceObj3_h.hits['fn_onmessage'] = 0;
 
     setTimeout(function() {
-      ok(gEventSourceObj3_h.hits['fn_onmessage'] == 0, "Test 3.h failed");
+      ok(gEventSourceObj3_h.hits['fn_onmessage'] > 1, "Test 3.h.1 failed");
+      if (gEventSourceObj3_h.hits['fn_onmessage'] > 1) {
+        ok(fnMessageListenerTest3h.msg_ok, "Test 3.h.2 failed");
+        ok(fnMessageListenerTest3h.id_ok, "Test 3.h.3 failed");
+      }
       gEventSourceObj3_h.close();
       setTestHasFinished(test_id);
-    }, parseInt(1500*stress_factor));
+    }, parseInt(3000*stress_factor));
   }
 
 // in order to test (4)
 //   a) close the object when it is in use, which is being processed and that is expected
 //      to dispatch more eventlisteners
 //   b) remove an eventlistener in use
 
   function fn_onmessage4_a(e)
@@ -539,18 +553,16 @@ https://bugzilla.mozilla.org/show_bug.cg
     gEventSourceObj6 = new EventSource("somedatas.resource");
     var fn_somedata = function(e) {
       if (fn_somedata.expected == 0) {
         ok(e.data == "123456789\n123456789123456789\n123456789123456789123456789123456789\n 123456789123456789123456789123456789123456789123456789123456789123456789\nçãá\"\'@`~Ý Ḿyyyy",
           "Test 6.a failed");
       } else if (fn_somedata.expected == 1) {
         ok(e.data == " :xxabcdefghij\nçãá\"\'@`~Ý Ḿyyyy : zz",
           "Test 6.b failed");
-      } else if (fn_somedata.expected == 2) {
-        ok(e.data == "1", "Test 6.c failed");
         gEventSourceObj6.close();
       } else {
         ok(false, "Test 6 failed (unexpected message event)");
       }
       fn_somedata.expected++;
     }
     fn_somedata.expected = 0;
     gEventSourceObj6.onmessage = fn_somedata;